diff --git a/.github/workflows/python_actions.yml b/.github/workflows/python_actions.yml index 029c2ce..dfccde6 100644 --- a/.github/workflows/python_actions.yml +++ b/.github/workflows/python_actions.yml @@ -53,12 +53,12 @@ jobs: uses: ./support/actions/install-matplotlib - name: Lint with flake8 - run: flake8 examples + run: flake8 examples balanced_random learning sudoku synfire - name: Lint with pylint uses: ./support/actions/pylint with: - package: examples + package: examples balanced_random learning sudoku synfire exitcheck: 39 validate: @@ -72,9 +72,11 @@ jobs: repository: SpiNNakerManchester/SupportScripts path: support - name: Run rat copyright enforcement + if: matrix.python-version == 3.12 uses: ./support/actions/check-copyrights with: config_file: rat_asl20.xml - name: Validate CITATION.cff + if: matrix.python-version == 3.12 uses: dieghernan/cff-validator@main diff --git a/.gitignore b/.gitignore index 06205f5..75a89e4 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,5 @@ __pycache__ .pytest_cache *application_generated_data_files/ *reports/ +.cache/ .mypy_cache/ diff --git a/.ratexcludes b/.ratexcludes index f63e490..0477ab4 100644 --- a/.ratexcludes +++ b/.ratexcludes @@ -8,4 +8,11 @@ **/SpiNNFrontEndCommon/** **/sPyNNaker/** **/sPyNNaker8/** +**/.pylintrc +**/*.dll +**/*.exe +**/*.png +**/*linux +**/*osx +**/*.exe **/.pylintrc \ No newline at end of file diff --git a/CITATION.cff b/CITATION.cff index 733367a..9f3a02f 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -105,4 +105,4 @@ contact: name: SpiNNaker Software Team post-code: M13 9PL license: Apache-2.0 -repository: https://github.com/SpiNNakerManchester/PyNN8Examples +repository: https://github.com/SpiNNakerManchester/PyNNExamples diff --git a/balanced_random/__init__.py b/balanced_random/__init__.py new file mode 100644 index 0000000..6725518 --- /dev/null +++ b/balanced_random/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/balanced_random/balanced_random.py b/balanced_random/balanced_random.py new file mode 100644 index 0000000..a2c4777 --- /dev/null +++ b/balanced_random/balanced_random.py @@ -0,0 +1,111 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import matplotlib.pyplot as pylab +import numpy +from pyNN.random import RandomDistribution +from pyNN.utility.plotting import Figure, Panel +import pyNN.spiNNaker as p + +p.setup(timestep=0.1) +p.set_number_of_neurons_per_core(p.IF_curr_exp, 64) +p.set_number_of_neurons_per_core(p.SpikeSourcePoisson, 64) +n_neurons = 500 +n_exc = int(round(n_neurons * 0.8)) +n_inh = int(round(n_neurons * 0.2)) +weight_exc = 0.1 +weight_inh = -5.0 * weight_exc +weight_input = 0.001 + +pop_input = p.Population(100, p.SpikeSourcePoisson(rate=0.0), + additional_parameters={ + "max_rate": 50.0, + "seed": 0}, + label="Input") + +pop_exc = p.Population(n_exc, p.IF_curr_exp, label="Excitatory", seed=1) +pop_inh = p.Population(n_inh, p.IF_curr_exp, label="Inhibitory", seed=2) +stim_exc = p.Population( + n_exc, p.SpikeSourcePoisson(rate=1000.0), label="Stim_Exc", + additional_parameters={"seed": 3}) +stim_inh = p.Population( + n_inh, p.SpikeSourcePoisson(rate=1000.0), label="Stim_Inh", + additional_parameters={"seed": 4}) + +delays_exc = RandomDistribution( + "normal_clipped", mu=1.5, sigma=0.75, low=1.0, high=1.6) +weights_exc = RandomDistribution( + "normal_clipped", mu=weight_exc, sigma=0.1, low=0, high=numpy.inf) +conn_exc = p.FixedProbabilityConnector(0.1) +synapse_exc = p.StaticSynapse(weight=weights_exc, delay=delays_exc) +delays_inh = RandomDistribution( + "normal_clipped", mu=0.75, sigma=0.375, low=1.0, high=1.6) +weights_inh = RandomDistribution( + "normal_clipped", mu=weight_inh, sigma=0.1, low=-numpy.inf, high=0) +conn_inh = p.FixedProbabilityConnector(0.1) +synapse_inh = p.StaticSynapse(weight=weights_inh, delay=delays_inh) +p.Projection( + pop_exc, pop_exc, conn_exc, synapse_exc, receptor_type="excitatory") +p.Projection( + pop_exc, pop_inh, conn_exc, synapse_exc, receptor_type="excitatory") +p.Projection( + pop_inh, pop_inh, conn_inh, synapse_inh, receptor_type="inhibitory") +p.Projection( + pop_inh, pop_exc, conn_inh, synapse_inh, receptor_type="inhibitory") + +conn_stim = p.OneToOneConnector() +synapse_stim = p.StaticSynapse(weight=weight_exc, delay=1.0) +p.Projection( + stim_exc, pop_exc, conn_stim, synapse_stim, receptor_type="excitatory") +p.Projection( + stim_inh, pop_inh, conn_stim, synapse_stim, receptor_type="excitatory") + +delays_input = RandomDistribution( + "normal_clipped", mu=1.5, sigma=0.75, low=1.0, high=1.6) +weights_input = RandomDistribution( + "normal_clipped", mu=weight_input, sigma=0.01, low=0, high=numpy.inf) +p.Projection(pop_input, pop_exc, p.AllToAllConnector(), p.StaticSynapse( + weight=weights_input, delay=delays_input)) + +pop_exc.initialize( + v=RandomDistribution("uniform", low=-65.0, high=-55.0)) +pop_inh.initialize( + v=RandomDistribution("uniform", low=-65.0, high=-55.0)) + +pop_exc.record("spikes") + +p.run(1000) + +pop_input.set(rate=50.0) +p.run(1000) + +pop_input.set(rate=10.0) +p.run(1000) + +pop_input.set(rate=20.0) +p.run(1000) + +data = pop_exc.get_data("spikes") +end_time = p.get_current_time() + +p.end() + +Figure( + # raster plot of the presynaptic neuron spike times + Panel(data.segments[0].spiketrains, + yticks=True, markersize=2.0, xlim=(0, end_time)), + title="Balanced Random Network", + annotations="Simulated with {}".format(p.name()) +) +pylab.show() diff --git a/balanced_random/split/balanced_random_split.py b/balanced_random/split/balanced_random_split.py new file mode 100755 index 0000000..94a7902 --- /dev/null +++ b/balanced_random/split/balanced_random_split.py @@ -0,0 +1,118 @@ +import pylab +import numpy +from pyNN.random import RandomDistribution +from pyNN.utility.plotting import Figure, Panel +import pyNN.spiNNaker as p +from spynnaker.pyNN.extra_algorithms.splitter_components import ( + SplitterPoissonDelegate, SplitterAbstractPopulationVertexNeuronsSynapses) + +p.setup(timestep=0.1, time_scale_factor=1) +p.set_number_of_neurons_per_core(p.IF_curr_exp, 64) +p.set_number_of_neurons_per_core(p.SpikeSourcePoisson, 64) +n_neurons = 500 +n_exc = int(round(n_neurons * 0.8)) +n_inh = int(round(n_neurons * 0.2)) +weight_exc = 0.1 +weight_inh = -5.0 * weight_exc +weight_input = 0.001 + +pop_input_splitter = SplitterPoissonDelegate() +pop_input = p.Population(100, p.SpikeSourcePoisson(rate=0.0), + additional_parameters={ + "max_rate": 50.0, + "seed": 0, + "splitter": pop_input_splitter}, + label="Input") + +pop_exc_splitter = \ + SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +pop_exc = p.Population(n_exc, p.IF_curr_exp, label="Excitatory", + additional_parameters={"splitter": pop_exc_splitter, + "seed": 1}) +pop_inh_splitter = \ + SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +pop_inh = p.Population(n_inh, p.IF_curr_exp, label="Inhibitory", + additional_parameters={"splitter": pop_inh_splitter, + "seed": 2}) +stim_exc_splitter = SplitterPoissonDelegate() +stim_exc = p.Population( + n_exc, p.SpikeSourcePoisson(rate=1000.0), label="Stim_Exc", + additional_parameters={"seed": 3, "splitter": stim_exc_splitter}) +stim_inh_splitter = SplitterPoissonDelegate() +stim_inh = p.Population( + n_inh, p.SpikeSourcePoisson(rate=1000.0), label="Stim_Inh", + additional_parameters={"seed": 4, "splitter": stim_inh_splitter}) + +delays_exc = RandomDistribution( + "normal_clipped", mu=1.5, sigma=0.75, low=1.0, high=1.6) +weights_exc = RandomDistribution( + "normal_clipped", mu=weight_exc, sigma=0.1, low=0, high=numpy.inf) +conn_exc = p.FixedProbabilityConnector(0.1) +synapse_exc = p.StaticSynapse(weight=weights_exc, delay=delays_exc) +delays_inh = RandomDistribution( + "normal_clipped", mu=0.75, sigma=0.375, low=1.0, high=1.6) +weights_inh = RandomDistribution( + "normal_clipped", mu=weight_inh, sigma=0.1, low=-numpy.inf, high=0) +conn_inh = p.FixedProbabilityConnector(0.1) +synapse_inh = p.StaticSynapse(weight=weights_inh, delay=delays_inh) +p.Projection( + pop_exc, pop_exc, conn_exc, synapse_exc, receptor_type="excitatory", + label="exc_exc") +p.Projection( + pop_exc, pop_inh, conn_exc, synapse_exc, receptor_type="excitatory", + label="exc_inh") +p.Projection( + pop_inh, pop_inh, conn_inh, synapse_inh, receptor_type="inhibitory", + label="inh_inh") +p.Projection( + pop_inh, pop_exc, conn_inh, synapse_inh, receptor_type="inhibitory", + label="inh_exc") + +conn_stim = p.OneToOneConnector() +synapse_stim = p.StaticSynapse(weight=weight_exc, delay=1.0) +p.Projection( + stim_exc, pop_exc, conn_stim, synapse_stim, receptor_type="excitatory", + label="stim_exc_exc") +p.Projection( + stim_inh, pop_inh, conn_stim, synapse_stim, receptor_type="excitatory", + label="stim_inh_inh") + +delays_input = RandomDistribution( + "normal_clipped", mu=1.5, sigma=0.75, low=1.0, high=1.6) +weights_input = RandomDistribution( + "normal_clipped", mu=weight_input, sigma=0.01, low=0, high=numpy.inf) +p.Projection(pop_input, pop_exc, p.AllToAllConnector(), p.StaticSynapse( + weight=weights_input, delay=delays_input), + label="input_exc") + +pop_exc.initialize( + v=RandomDistribution("uniform", low=-65.0, high=-55.0)) +pop_inh.initialize( + v=RandomDistribution("uniform", low=-65.0, high=-55.0)) + +pop_exc.record("spikes") + +p.run(1000) + +pop_input.set(rate=50.0) +p.run(1000) + +pop_input.set(rate=10.0) +p.run(1000) + +pop_input.set(rate=20.0) +p.run(1000) + +data = pop_exc.get_data("spikes") +end_time = p.get_current_time() + +p.end() + +Figure( + # raster plot of the presynaptic neuron spike times + Panel(data.segments[0].spiketrains, + yticks=True, markersize=2.0, xlim=(0, end_time)), + title="Balanced Random Network", + annotations="Simulated with {}".format(p.name()) +) +pylab.show() diff --git a/balanced_random/split/spynnaker.cfg b/balanced_random/split/spynnaker.cfg new file mode 100644 index 0000000..3ef3dab --- /dev/null +++ b/balanced_random/split/spynnaker.cfg @@ -0,0 +1,2 @@ +[Mode] +violate_1ms_wall_clock_restriction = True diff --git a/integration_tests/script_builder.py b/integration_tests/script_builder.py index dd0f398..99e9fc0 100644 --- a/integration_tests/script_builder.py +++ b/integration_tests/script_builder.py @@ -33,7 +33,9 @@ def build_scripts(self): too_long = {} too_long["stdp_triplet.py"] = "10 minutes" - self.create_test_scripts(["examples"], too_long, exceptions) + self.create_test_scripts( + ["examples","balanced_random", "learning", "synfire"], + too_long, exceptions) if __name__ == '__main__': diff --git a/integration_tests/test_scripts.py b/integration_tests/test_scripts.py index cf328b9..a107aab 100644 --- a/integration_tests/test_scripts.py +++ b/integration_tests/test_scripts.py @@ -13,7 +13,6 @@ # limitations under the License. from spinnaker_testbase import ScriptChecker -from unittest import SkipTest # pylint: disable=unused-import class TestScripts(ScriptChecker): @@ -40,6 +39,24 @@ def test_examples_hbp_neuroguidebook_example(self): def test_examples_partitioner_examples_splitter_usage(self): self.check_script("examples/partitioner_examples/splitter_usage.py") + def test_examples_split_examples_structural_plasticity_with_stdp_neuromodulated(self): + self.check_script("examples/split_examples/structural_plasticity_with_stdp_neuromodulated.py") + + def test_examples_split_examples_stdp_neuromodulated_example_split(self): + self.check_script("examples/split_examples/stdp_neuromodulated_example_split.py") + + def test_examples_split_examples_pynnBrunnelSplit(self): + self.check_script("examples/split_examples/pynnBrunnelSplit.py") + + def test_examples_split_examples_va_benchmark_split(self): + self.check_script("examples/split_examples/va_benchmark_split.py") + + def test_examples_balanced_random_balanced_random(self): + self.check_script("examples/balanced_random/balanced_random.py") + + def test_examples_balanced_random_split_balanced_random_split(self): + self.check_script("examples/balanced_random/split/balanced_random_split.py") + def test_examples_synfire_if_curr_exp_random(self): self.check_script("examples/synfire_if_curr_exp_random.py") @@ -55,6 +72,9 @@ def test_examples_if_curr_delta(self): def test_examples_structural_plasticity_without_stdp_2d(self): self.check_script("examples/structural_plasticity_without_stdp_2d.py") + def test_examples_structural_plasticity_with_stdp_neuromodulated_separate_pops(self): + self.check_script("examples/structural_plasticity_with_stdp_neuromodulated_separate_pops.py") + def test_examples_external_devices_examples_retina_example(self): self.check_script("examples/external_devices_examples/retina_example.py") @@ -71,14 +91,13 @@ def test_examples_external_devices_examples_live_examples_spike_io_interactive_d self.check_script("examples/external_devices_examples/live_examples/spike_io_interactive_demo_with_c_vis.py") def test_examples_external_devices_examples_live_examples_balanced_random_live_rate(self): - # Warning this test takes 125 seconds. - # raise skiptest is uncommented on branch tests - # raise SkipTest("125 seconds") self.check_script("examples/external_devices_examples/live_examples/balanced_random_live_rate.py") - def test_examples_external_devices_examples_pushbot_ethernet_example(self): - raise SkipTest("Needs a physical pushbot") - self.check_script("examples/external_devices_examples/pushbot_ethernet_example.py") + # Not testing file due to: Runs forever + # examples/external_devices_examples/pushbot_light_follower.py + + # Not testing file due to: Needs a physical pushbot + # examples/external_devices_examples/pushbot_ethernet_example.py def test_examples_external_devices_examples_pushbot_spinnaker_link_example(self): self.check_script("examples/external_devices_examples/pushbot_spinnaker_link_example.py") @@ -101,6 +120,12 @@ def test_examples_stdp_example_cond(self): def test_examples_stdp_pairing(self): self.check_script("examples/stdp_pairing.py") + def test_examples_simple_STDP(self): + self.check_script("examples/simple_STDP.py") + + def test_examples_stdp_neuromodulation_test(self): + self.check_script("examples/stdp_neuromodulation_test.py") + def test_examples_pynnBrunnel(self): self.check_script("examples/pynnBrunnel.py") @@ -110,18 +135,18 @@ def test_examples_synfire_if_curr_exp_get_weights(self): def test_examples_synfire_if_cond_exp(self): self.check_script("examples/synfire_if_cond_exp.py") + def test_examples_stdp_neuromodulated_example(self): + self.check_script("examples/stdp_neuromodulated_example.py") + def test_examples_stdp_curve_cond(self): - # Warning this test takes 121 seconds. - # raise skiptest is uncommented on branch tests - # raise SkipTest("121 seconds") self.check_script("examples/stdp_curve_cond.py") def test_examples_stdp_curve(self): - # Warning this test takes 118 seconds. - # raise skiptest is uncommented on branch tests - # raise SkipTest("118 seconds") self.check_script("examples/stdp_curve.py") + def test_examples_current_injection_example(self): + self.check_script("examples/current_injection_example.py") + def test_examples_stdp_example(self): self.check_script("examples/stdp_example.py") @@ -135,18 +160,12 @@ def test_examples_extra_models_examples_vogel_2011_vogels_2011_live(self): self.check_script("examples/extra_models_examples/vogel_2011/vogels_2011_live.py") def test_examples_extra_models_examples_vogel_2011_vogels_2011(self): - # Warning this test takes 698 seconds. - # raise skiptest is uncommented on branch tests - # raise SkipTest("698 seconds") self.check_script("examples/extra_models_examples/vogel_2011/vogels_2011.py") def test_examples_extra_models_examples_stdp_associative_memory(self): self.check_script("examples/extra_models_examples/stdp_associative_memory.py") def test_examples_extra_models_examples_stdp_triplet(self): - # Warning this test takes 10 minutes. - # raise skiptest is uncommented on branch tests - # raise SkipTest("10 minutes") self.check_script("examples/extra_models_examples/stdp_triplet.py") def test_examples_extra_models_examples_synfire_if_curr_dual_exp(self): @@ -166,3 +185,39 @@ def test_examples_extra_models_examples_IF_curr_exp_ca2_adaptive(self): def test_examples_extra_models_examples_IF_cond_exp_stoc(self): self.check_script("examples/extra_models_examples/IF_cond_exp_stoc.py") + + def test_balanced_random_balanced_random(self): + self.check_script("balanced_random/balanced_random.py") + + def test_balanced_random_split_balanced_random_split(self): + self.check_script("balanced_random/split/balanced_random_split.py") + + def test_learning_random_dist(self): + self.check_script("learning/random_dist.py") + + def test_learning_stdp(self): + self.check_script("learning/stdp.py") + + def test_learning_struct_pl(self): + self.check_script("learning/struct_pl.py") + + def test_learning_split_struct_pl_stdp_split(self): + self.check_script("learning/split/struct_pl_stdp_split.py") + + def test_learning_split_struct_pl_split(self): + self.check_script("learning/split/struct_pl_split.py") + + def test_learning_split_stdp_split(self): + self.check_script("learning/split/stdp_split.py") + + def test_learning_simple(self): + self.check_script("learning/simple.py") + + def test_learning_struct_pl_stdp(self): + self.check_script("learning/struct_pl_stdp.py") + + def test_synfire_synfire(self): + self.check_script("synfire/synfire.py") + + def test_synfire_synfire_collab(self): + self.check_script("synfire/synfire_collab.py") diff --git a/learning/__init__.py b/learning/__init__.py new file mode 100644 index 0000000..6725518 --- /dev/null +++ b/learning/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/learning/random_dist.py b/learning/random_dist.py new file mode 100644 index 0000000..5a70254 --- /dev/null +++ b/learning/random_dist.py @@ -0,0 +1,72 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import matplotlib.pyplot as plt +from pyNN.random import RandomDistribution +import pyNN.utility.plotting as plot +import pyNN.spiNNaker as sim + +n_neurons = 1000 +n_exc = int(round(n_neurons * 0.8)) +n_inh = int(round(n_neurons * 0.2)) +simtime = 1000 + +sim.setup(timestep=0.1) + +pop_exc = sim.Population(n_exc, sim.IF_curr_exp(), label="Excitatory") +pop_inh = sim.Population(n_inh, sim.IF_curr_exp(), label="Inhibitory") +stim_exc = sim.Population(n_exc, sim.SpikeSourcePoisson(rate=10.0), + label="Stim_Exc") +stim_inh = sim.Population(n_inh, sim.SpikeSourcePoisson(rate=10.0), + label="Stim_Inh") + +synapse_exc = sim.StaticSynapse(weight=0.2, delay=2.0) +synapse_inh = sim.StaticSynapse(weight=-1.0, delay=2.0) +sim.Projection(pop_exc, pop_exc, sim.FixedProbabilityConnector(0.1), + synapse_type=synapse_exc, receptor_type="excitatory") +sim.Projection(pop_exc, pop_inh, sim.FixedProbabilityConnector(0.1), + synapse_type=synapse_exc, receptor_type="excitatory") +sim.Projection(pop_inh, pop_inh, sim.FixedProbabilityConnector(0.1), + synapse_type=synapse_inh, receptor_type="inhibitory") +sim.Projection(pop_inh, pop_exc, sim.FixedProbabilityConnector(0.1), + synapse_type=synapse_inh, receptor_type="inhibitory") + +delays = RandomDistribution("uniform", parameters_pos=[1.0, 1.6]) +conn_stim = sim.OneToOneConnector() +synapse_stim = sim.StaticSynapse(weight=2.0, delay=delays) + +sim.Projection(stim_exc, pop_exc, conn_stim, synapse_type=synapse_stim, + receptor_type="excitatory") +sim.Projection(stim_inh, pop_inh, conn_stim, synapse_type=synapse_stim, + receptor_type="excitatory") + +pop_exc.initialize( + v=RandomDistribution("uniform", parameters_pos=[-65.0, -55.0])) +pop_inh.initialize( + v=RandomDistribution("uniform", parameters_pos=[-65.0, -55.0])) +pop_exc.record("spikes") +sim.run(simtime) + +neo = pop_exc.get_data(variables=["spikes"]) +spikes = neo.segments[0].spiketrains + +sim.end() + +plot.Figure( + # plot spikes + plot.Panel(spikes, yticks=True, markersize=5, xlim=(0, simtime)), + title="Balanced Random Network Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/learning/simple.py b/learning/simple.py new file mode 100644 index 0000000..8e29136 --- /dev/null +++ b/learning/simple.py @@ -0,0 +1,48 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pyNN.utility.plotting as plot +import matplotlib.pyplot as plt +import pyNN.spiNNaker as sim + +sim.setup(timestep=1.0, n_boards_required=1) +machine = sim.get_machine() +sim.set_number_of_neurons_per_core(sim.IF_curr_exp, 100) + +pop_1 = sim.Population(1, sim.IF_curr_exp(), label="pop_1") +input_pop = sim.Population( + 1, sim.SpikeSourceArray(spike_times=[0]), label="input") +input_proj = sim.Projection(input_pop, pop_1, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5, delay=1)) +pop_1.record(["spikes", "v"]) +simtime = 10 +sim.run(simtime) + +neo = pop_1.get_data(variables=["spikes", "v"]) +spikes = neo.segments[0].spiketrains +print(spikes) +v = neo.segments[0].filter(name='v')[0] +print(v) +sim.end() + +plot.Figure( + # plot voltage for first ([0]) neuron + plot.Panel(v, ylabel="Membrane potential (mV)", + data_labels=[pop_1.label], yticks=True, xlim=(0, simtime)), + # plot spikes (or in this case spike) + plot.Panel(spikes, yticks=True, markersize=5, xlim=(0, simtime)), + title="Simple Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/learning/split/spynnaker.cfg b/learning/split/spynnaker.cfg new file mode 100644 index 0000000..3ef3dab --- /dev/null +++ b/learning/split/spynnaker.cfg @@ -0,0 +1,2 @@ +[Mode] +violate_1ms_wall_clock_restriction = True diff --git a/learning/split/stdp_split.py b/learning/split/stdp_split.py new file mode 100755 index 0000000..fc9e531 --- /dev/null +++ b/learning/split/stdp_split.py @@ -0,0 +1,81 @@ +import pyNN.utility.plotting as plot +import matplotlib.pyplot as plt +import pyNN.spiNNaker as sim +from spynnaker.pyNN.extra_algorithms.splitter_components import ( + SplitterAbstractPopulationVertexNeuronsSynapses, SplitterPoissonDelegate) + +n_neurons = 192 +simtime = 5000 + +sim.setup(timestep=1.0) +sim.set_number_of_neurons_per_core(sim.IF_curr_exp, 64) + +pre_splitter = SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +pre_pop = sim.Population( + n_neurons, sim.IF_curr_exp(), label="Pre", additional_parameters={ + "splitter": pre_splitter}) +post_splitter = SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +post_pop = sim.Population( + n_neurons, sim.IF_curr_exp(), label="Post", additional_parameters={ + "splitter": post_splitter}) +pre_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Pre", + additional_parameters={"splitter": SplitterPoissonDelegate()}) +post_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Post", + additional_parameters={"splitter": SplitterPoissonDelegate()}) + +pre_pop.record("spikes") +post_pop.record("spikes") + +training = sim.Population( + n_neurons, + sim.SpikeSourcePoisson(rate=10.0, start=1500.0, duration=1500.0), + label="Training", + additional_parameters={"splitter": SplitterPoissonDelegate()}) + +sim.Projection(pre_noise, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) +sim.Projection(post_noise, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) + +sim.Projection(training, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=1.0)) +sim.Projection(training, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=10.0)) + +timing_rule = sim.SpikePairRule(tau_plus=20.0, tau_minus=20.0, + A_plus=0.5, A_minus=0.5) +weight_rule = sim.AdditiveWeightDependence(w_max=5.0, w_min=0.0) + +stdp_model = sim.STDPMechanism(timing_dependence=timing_rule, + weight_dependence=weight_rule, + weight=0.0, delay=5.0) + +stdp_projection = sim.Projection(pre_pop, post_pop, sim.OneToOneConnector(), + # sim.StaticSynapse(0, 5.0)) + synapse_type=stdp_model) + +sim.run(simtime) + +pre_neo = pre_pop.get_data(variables=["spikes"]) +pre_spikes = pre_neo.segments[0].spiketrains + +post_neo = post_pop.get_data(variables=["spikes"]) +post_spikes = post_neo.segments[0].spiketrains + +print(stdp_projection.get('weight', format="list")) + +sim.end() + +line_properties = [{'color': 'red', 'markersize': 5}, + {'color': 'blue', 'markersize': 2}] + +plot.Figure( + # plot spikes + plot.Panel(pre_spikes, post_spikes, yticks=True, xlim=(0, simtime), + line_properties=line_properties), + title="STDP Network Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/learning/split/struct_pl_split.py b/learning/split/struct_pl_split.py new file mode 100755 index 0000000..0ea0301 --- /dev/null +++ b/learning/split/struct_pl_split.py @@ -0,0 +1,102 @@ +import matplotlib.pyplot as plt +import numpy +import pyNN.utility.plotting as plot +import pyNN.spiNNaker as sim +from spynnaker.pyNN.extra_algorithms.splitter_components import ( + SplitterAbstractPopulationVertexNeuronsSynapses, SplitterPoissonDelegate) + +n_neurons = 64 +simtime = 5000 + +sim.setup(timestep=1.0) + +pre_splitter = SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +pre_pop = sim.Population( + n_neurons, sim.IF_curr_exp(), label="Pre", additional_parameters={ + "splitter": pre_splitter}) +post_splitter = SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +post_pop = sim.Population( + n_neurons, sim.IF_curr_exp(), label="Post", additional_parameters={ + "splitter": post_splitter}) +pre_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Pre", + additional_parameters={"splitter": SplitterPoissonDelegate()}) +post_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Post", + additional_parameters={"splitter": SplitterPoissonDelegate()}) + +pre_pop.record("spikes") +post_pop.record("spikes") + +training = sim.Population( + n_neurons, + sim.SpikeSourcePoisson(rate=10.0, start=1500.0, duration=1500.0), + label="Training", + additional_parameters={"splitter": SplitterPoissonDelegate()}) + +sim.Projection(pre_noise, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) +sim.Projection(post_noise, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) + +sim.Projection(training, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=1.0)) +sim.Projection(training, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=10.0)) + +# Structurally plastic connection between pre_pop and post_pop +partner_selection_last_neuron = sim.RandomSelection() +formation_distance = sim.DistanceDependentFormation( + grid=[numpy.sqrt(n_neurons), numpy.sqrt(n_neurons)], + sigma_form_forward=.5 # spread of feed-forward connections +) +elimination_weight = sim.RandomByWeightElimination( + threshold=.2 # Use same weight as initial weight for static connections +) +structure_model_without_stdp = sim.StructuralMechanismStatic( + # Partner selection, formation and elimination rules from above + partner_selection_last_neuron, formation_distance, elimination_weight, + # Use this weight when creating a new synapse + initial_weight=5, + # Use this weight for synapses at start of simulation + weight=5, + # Use this delay when creating a new synapse + initial_delay=5, + # Use this weight for synapses at the start of simulation + delay=5, + # Maximum allowed fan-in per target-layer neuron + s_max=32, + # Frequency of rewiring in Hz + f_rew=10 ** 4 +) + +plastic_projection = sim.Projection( + pre_pop, post_pop, + sim.FixedProbabilityConnector(0.), # No initial connections + synapse_type=structure_model_without_stdp, + label="structurally_plastic_projection" +) + +sim.run(simtime) + +pre_neo = pre_pop.get_data(variables=["spikes"]) +pre_spikes = pre_neo.segments[0].spiketrains + +post_neo = post_pop.get_data(variables=["spikes"]) +post_spikes = post_neo.segments[0].spiketrains + +print(plastic_projection.get('weight', format="list")) + +sim.end() + +line_properties = [{'color': 'red', 'markersize': 5}, + {'color': 'blue', 'markersize': 2}] + +plot.Figure( + # plot spikes + plot.Panel(pre_spikes, post_spikes, yticks=True, xlim=(0, simtime), + line_properties=line_properties), + title="STDP Network Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/learning/split/struct_pl_stdp_split.py b/learning/split/struct_pl_stdp_split.py new file mode 100755 index 0000000..2c05567 --- /dev/null +++ b/learning/split/struct_pl_stdp_split.py @@ -0,0 +1,112 @@ +import matplotlib.pyplot as plt +import numpy +import pyNN.spiNNaker as sim +import pyNN.utility.plotting as plot +from spynnaker.pyNN.extra_algorithms.splitter_components import ( + SplitterAbstractPopulationVertexNeuronsSynapses, SplitterPoissonDelegate) + +n_neurons = 192 +simtime = 5000 + +sim.setup(timestep=1.0) + +sim.set_number_of_neurons_per_core(sim.IF_curr_exp, 64) +pre_splitter = SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +pre_pop = sim.Population( + n_neurons, sim.IF_curr_exp(), label="Pre", additional_parameters={ + "splitter": pre_splitter}) +post_splitter = SplitterAbstractPopulationVertexNeuronsSynapses(1, 128, False) +post_pop = sim.Population( + n_neurons, sim.IF_curr_exp(), label="Post", additional_parameters={ + "splitter": post_splitter}) +pre_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Pre", + additional_parameters={"splitter": SplitterPoissonDelegate()}) +post_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Post", + additional_parameters={"splitter": SplitterPoissonDelegate()}) + +pre_pop.record("spikes") +post_pop.record("spikes") + +training = sim.Population( + n_neurons, + sim.SpikeSourcePoisson(rate=10.0, start=1500.0, duration=1500.0), + label="Training", + additional_parameters={"splitter": SplitterPoissonDelegate()}) + +sim.Projection(pre_noise, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) +sim.Projection(post_noise, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) + +sim.Projection(training, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=1.0)) +sim.Projection(training, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=10.0)) + +timing_rule = sim.SpikePairRule(tau_plus=20.0, tau_minus=20.0, + A_plus=0.5, A_minus=0.5) +weight_rule = sim.AdditiveWeightDependence(w_max=5.0, w_min=0.0) + +partner_selection_last_neuron = sim.RandomSelection() +formation_distance = sim.DistanceDependentFormation( + grid=[numpy.sqrt(n_neurons), numpy.sqrt(n_neurons)], + sigma_form_forward=.5 # spread of feed-forward connections +) +elimination_weight = sim.RandomByWeightElimination( + prob_elim_potentiated=0, # no eliminations for potentiated synapses + prob_elim_depressed=0, # no elimination for depressed synapses + threshold=0.5 # Use same weight as initial weight for static connections +) +structure_model_with_stdp = sim.StructuralMechanismSTDP( + # Partner selection, formation and elimination rules from above + partner_selection_last_neuron, formation_distance, elimination_weight, + # Use this weight when creating a new synapse + initial_weight=0, + # Use this weight for synapses at start of simulation + weight=0, + # Use this delay when creating a new synapse + initial_delay=5, + # Use this weight for synapses at the start of simulation + delay=5, + # Maximum allowed fan-in per target-layer neuron + s_max=64, + # Frequency of rewiring in Hz + f_rew=10 ** 4, + # STDP rules + timing_dependence=sim.SpikePairRule( + tau_plus=20., tau_minus=20.0, A_plus=0.5, A_minus=0.5), + weight_dependence=sim.AdditiveWeightDependence(w_min=0, w_max=5.) +) + +plastic_projection = sim.Projection( + pre_pop, post_pop, + sim.FixedProbabilityConnector(0.), # No initial connections + synapse_type=structure_model_with_stdp, + label="structurally_plastic_projection" +) + +sim.run(simtime) + +pre_neo = pre_pop.get_data(variables=["spikes"]) +pre_spikes = pre_neo.segments[0].spiketrains + +post_neo = post_pop.get_data(variables=["spikes"]) +post_spikes = post_neo.segments[0].spiketrains + +print(plastic_projection.get('weight', format="list")) + +sim.end() + +line_properties = [{'color': 'red', 'markersize': 5}, + {'color': 'blue', 'markersize': 2}] + +plot.Figure( + # plot spikes + plot.Panel(pre_spikes, post_spikes, yticks=True, xlim=(0, simtime), + line_properties=line_properties), + title="STDP Network Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/learning/stdp.py b/learning/stdp.py new file mode 100644 index 0000000..9bde57e --- /dev/null +++ b/learning/stdp.py @@ -0,0 +1,82 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import pyNN.utility.plotting as plot +import matplotlib.pyplot as plt +import pyNN.spiNNaker as sim + +n_neurons = 100 +simtime = 5000 + +sim.setup(timestep=1.0) + +pre_pop = sim.Population(n_neurons, sim.IF_curr_exp(), label="Pre") +post_pop = sim.Population(n_neurons, sim.IF_curr_exp(), label="Post") +pre_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Pre") +post_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Post") + +pre_pop.record("spikes") +post_pop.record("spikes") + +training = sim.Population( + n_neurons, + sim.SpikeSourcePoisson(rate=10.0, start=1500.0, duration=1500.0), + label="Training") + +sim.Projection(pre_noise, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) +sim.Projection(post_noise, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) + +sim.Projection(training, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=1.0)) +sim.Projection(training, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=10.0)) + +timing_rule = sim.SpikePairRule(tau_plus=20.0, tau_minus=20.0, + A_plus=0.5, A_minus=0.5) +weight_rule = sim.AdditiveWeightDependence(w_max=5.0, w_min=0.0) + +stdp_model = sim.STDPMechanism(timing_dependence=timing_rule, + weight_dependence=weight_rule, + weight=0.0, delay=5.0) + +stdp_projection = sim.Projection(pre_pop, post_pop, sim.OneToOneConnector(), + synapse_type=stdp_model) + +sim.run(simtime) + +pre_neo = pre_pop.get_data(variables=["spikes"]) +pre_spikes = pre_neo.segments[0].spiketrains + +post_neo = post_pop.get_data(variables=["spikes"]) +post_spikes = post_neo.segments[0].spiketrains + +print(stdp_projection.get('weight', format="list")) + +sim.end() + +line_properties = [{'color': 'red', 'markersize': 5}, + {'color': 'blue', 'markersize': 2}] + +plot.Figure( + # plot spikes + plot.Panel(pre_spikes, post_spikes, yticks=True, xlim=(0, simtime), + line_properties=line_properties), + title="STDP Network Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/learning/struct_pl.py b/learning/struct_pl.py new file mode 100755 index 0000000..d2f09af --- /dev/null +++ b/learning/struct_pl.py @@ -0,0 +1,95 @@ +import pyNN.utility.plotting as plot +import matplotlib.pyplot as plt +import numpy +import pyNN.spiNNaker as sim + +n_neurons = 100 +simtime = 5000 + +sim.setup(timestep=1.0) + +pre_pop = sim.Population(n_neurons, sim.IF_curr_exp(), label="Pre") +post_pop = sim.Population(n_neurons, sim.IF_curr_exp(), label="Post") +pre_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Pre") +post_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Post") + +pre_pop.record("spikes") +post_pop.record("spikes") + +training = sim.Population( + n_neurons, + sim.SpikeSourcePoisson(rate=10.0, start=1500.0, duration=1500.0), + label="Training") + +sim.Projection(pre_noise, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) +sim.Projection(post_noise, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) + +sim.Projection(training, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=1.0)) +sim.Projection(training, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=10.0)) + +timing_rule = sim.SpikePairRule(tau_plus=20.0, tau_minus=20.0, + A_plus=0.5, A_minus=0.5) +weight_rule = sim.AdditiveWeightDependence(w_max=5.0, w_min=0.0) + +# Structurally plastic connection between pre_pop and post_pop +partner_selection_last_neuron = sim.RandomSelection() +formation_distance = sim.DistanceDependentFormation( + grid=[numpy.sqrt(n_neurons), numpy.sqrt(n_neurons)], + sigma_form_forward=.5 # spread of feed-forward connections +) +elimination_weight = sim.RandomByWeightElimination( + threshold=.2 # Use same weight as initial weight for static connections +) +structure_model_without_stdp = sim.StructuralMechanismStatic( + # Partner selection, formation and elimination rules from above + partner_selection_last_neuron, formation_distance, elimination_weight, + # Use this weight when creating a new synapse + initial_weight=5, + # Use this weight for synapses at start of simulation + weight=5, + # Use this delay when creating a new synapse + initial_delay=5, + # Use this weight for synapses at the start of simulation + delay=5, + # Maximum allowed fan-in per target-layer neuron + s_max=32, + # Frequency of rewiring in Hz + f_rew=10 ** 4 +) + +plastic_projection = sim.Projection( + pre_pop, post_pop, + sim.FixedProbabilityConnector(0.), # No initial connections + synapse_type=structure_model_without_stdp, + label="structurally_plastic_projection" +) + +sim.run(simtime) + +pre_neo = pre_pop.get_data(variables=["spikes"]) +pre_spikes = pre_neo.segments[0].spiketrains + +post_neo = post_pop.get_data(variables=["spikes"]) +post_spikes = post_neo.segments[0].spiketrains + +print(plastic_projection.get('weight', format="list")) + +sim.end() + +line_properties = [{'color': 'red', 'markersize': 5}, + {'color': 'blue', 'markersize': 2}] + +plot.Figure( + # plot spikes + plot.Panel(pre_spikes, post_spikes, yticks=True, xlim=(0, simtime), + line_properties=line_properties), + title="STDP Network Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/learning/struct_pl_stdp.py b/learning/struct_pl_stdp.py new file mode 100755 index 0000000..df6194e --- /dev/null +++ b/learning/struct_pl_stdp.py @@ -0,0 +1,100 @@ +import pyNN.utility.plotting as plot +import matplotlib.pyplot as plt +import numpy +import pyNN.spiNNaker as sim + +n_neurons = 100 +simtime = 5000 + +sim.setup(timestep=1.0) + +pre_pop = sim.Population(n_neurons, sim.IF_curr_exp(), label="Pre") +post_pop = sim.Population(n_neurons, sim.IF_curr_exp(), label="Post") +pre_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Pre") +post_noise = sim.Population( + n_neurons, sim.SpikeSourcePoisson(rate=10.0), label="Noise_Post") + +pre_pop.record("spikes") +post_pop.record("spikes") + +training = sim.Population( + n_neurons, + sim.SpikeSourcePoisson(rate=10.0, start=1500.0, duration=1500.0), + label="Training") + +sim.Projection(pre_noise, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) +sim.Projection(post_noise, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=2.0)) + +sim.Projection(training, pre_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=1.0)) +sim.Projection(training, post_pop, sim.OneToOneConnector(), + synapse_type=sim.StaticSynapse(weight=5.0, delay=10.0)) + +timing_rule = sim.SpikePairRule(tau_plus=20.0, tau_minus=20.0, + A_plus=0.5, A_minus=0.5) +weight_rule = sim.AdditiveWeightDependence(w_max=5.0, w_min=0.0) + +partner_selection_last_neuron = sim.RandomSelection() +formation_distance = sim.DistanceDependentFormation( + grid=[numpy.sqrt(n_neurons), numpy.sqrt(n_neurons)], + sigma_form_forward=.5 # spread of feed-forward connections +) +elimination_weight = sim.RandomByWeightElimination( + prob_elim_potentiated=0, # no eliminations for potentiated synapses + prob_elim_depressed=0, # no elimination for depressed synapses + threshold=0.5 # Use same weight as initial weight for static connections +) +structure_model_with_stdp = sim.StructuralMechanismSTDP( + # Partner selection, formation and elimination rules from above + partner_selection_last_neuron, formation_distance, elimination_weight, + # Use this weight when creating a new synapse + initial_weight=0, + # Use this weight for synapses at start of simulation + weight=0, + # Use this delay when creating a new synapse + initial_delay=5, + # Use this weight for synapses at the start of simulation + delay=5, + # Maximum allowed fan-in per target-layer neuron + s_max=64, + # Frequency of rewiring in Hz + f_rew=10 ** 4, + # STDP rules + timing_dependence=sim.SpikePairRule( + tau_plus=20., tau_minus=20.0, A_plus=0.5, A_minus=0.5), + weight_dependence=sim.AdditiveWeightDependence(w_min=0, w_max=5.) +) + +plastic_projection = sim.Projection( + pre_pop, post_pop, + sim.FixedProbabilityConnector(0.), # No initial connections + synapse_type=structure_model_with_stdp, + label="structurally_plastic_projection" +) + +sim.run(simtime) + +pre_neo = pre_pop.get_data(variables=["spikes"]) +pre_spikes = pre_neo.segments[0].spiketrains + +post_neo = post_pop.get_data(variables=["spikes"]) +post_spikes = post_neo.segments[0].spiketrains + +print(plastic_projection.get('weight', format="list")) + +sim.end() + +line_properties = [{'color': 'red', 'markersize': 5}, + {'color': 'blue', 'markersize': 2}] + +plot.Figure( + # plot spikes + plot.Panel(pre_spikes, post_spikes, yticks=True, xlim=(0, simtime), + line_properties=line_properties), + title="STDP Network Example", + annotations="Simulated with {}".format(sim.name()) +) +plt.show() diff --git a/pendulum/pendulum b/pendulum/pendulum new file mode 100755 index 0000000..4d4ab82 Binary files /dev/null and b/pendulum/pendulum differ diff --git a/pendulum/pendulum_follow_c_vis.py b/pendulum/pendulum_follow_c_vis.py new file mode 100644 index 0000000..6fb8ca6 --- /dev/null +++ b/pendulum/pendulum_follow_c_vis.py @@ -0,0 +1,208 @@ +import math +import os +import re +import subprocess +from time import time, sleep +from functools import partial +from threading import Thread +from matplotlib import pyplot +import numpy +import pyNN.spiNNaker as p +from spynnaker.pyNN.models.utility_models.spike_injector import SpikeInjector + +running = True + + +class CSVLine(): + def __init__(self, line): + if len(line) == 0: + raise EOFError + parts = [int(part.strip()) for part in line.split(",")] + if len(parts) < 4: + raise EOFError + self.x, self.y, self.p, send_time = parts + self.send_time = send_time / 1000.0 + + def __repr__(self): + return f"(x: {self.x}, y: {self.y}, send_time: {self.send_time})" + + def get_pos(self, min_x, min_y): + return self.x - min_x, self.y - min_y, self.send_time + + def get_spike(self, width, min_x, min_y): + return ((self.y - min_y) * width) + (self.x - min_x) + + +def make_kernel_circle(r, k_sz, weight, kernel): + var = int((k_sz+1)/2-1) + a = numpy.arange(0, 2 * math.pi, 0.01) + dx = numpy.round(r * numpy.sin(a)).astype("uint32") + dy = numpy.round(r * numpy.cos(a)).astype("uint32") + kernel[var + dx, var + dy] = weight + + + +def read_csv_line(f): + line = f.readline() + if not f: + return None + try: + return CSVLine(line) + except EOFError: + return None + + +def send_spikes(width, height, min_x, min_y, run_time, label, connection): + global running + start_time = None + max_x = min_x + width + max_y = min_y + height + with open("spikes.csv") as f: + first_time = -1 + line = read_csv_line(f) + while line and running: + send_time = line.send_time + if start_time is not None and send_time - start_time > run_time: + return + same_time_lines = [] + next_line = line + while next_line and next_line.send_time == send_time: + same_time_lines.append(next_line) + next_line = read_csv_line(f) + line = next_line + + filtered_lines = [ + ln for ln in same_time_lines + if (ln.x >= min_x and ln.x < max_x and ln.y >= min_y and + ln.y < max_y)] + + if not filtered_lines: + continue + + spikes = [s.get_spike(width, min_x, min_y) for s in filtered_lines] + spikes = spikes[:20] + + if first_time == -1: + first_time = send_time + start_time = time() + + sleep_time = (time() - start_time) - (send_time - first_time) + if sleep_time > 0: + sleep(sleep_time) + connection.send_spikes(label, spikes, send_full_keys=True) + running = False + + +WIDTH = 118 +HEIGHT = 118 +MIN_X = 450 +MIN_Y = 400 +PER_CORE_WIDTH = 16 +PER_CORE_HEIGHT = 16 +SPIF_IP = "spif-01" +SPIF_PORT = 3332 +POP_LABEL = "target" +SEND_POP_LABEL = "source" +RUN_TIME = 5000 +CHIP = (0, 0) + +scaler = 0.1 +k_sz = 39 +pos_w = 0.8 +neg_w = -1.0 + +kernel = numpy.zeros((k_sz, k_sz)) +make_kernel_circle(0.46*k_sz, k_sz, pos_w*scaler, kernel) +make_kernel_circle(0.41*k_sz, k_sz, neg_w*scaler, kernel) +make_kernel_circle(0.36*k_sz, k_sz, pos_w*scaler, kernel) +make_kernel_circle(0.26*k_sz, k_sz, neg_w*scaler, kernel) + +pyplot.imshow(kernel, interpolation='nearest') +pyplot.savefig("kernel.png") + +convolution = p.ConvolutionConnector(kernel_weights=kernel) +out_width, out_height = convolution.get_post_shape((WIDTH, HEIGHT)) + +print(f"Output {out_width} x {out_height}") + +vis_exe = os.path.abspath(os.path.join( + os.path.dirname(__file__), "pendulum")) +receiver = subprocess.Popen([vis_exe, "-input_dims", str(WIDTH), str(HEIGHT), + "-output_dims", str(out_width), str(out_height), + str(k_sz // 2), str(PER_CORE_WIDTH), + str(PER_CORE_HEIGHT)], + stderr=subprocess.PIPE) +firstline = str(receiver.stderr.readline(), "UTF-8") +match = re.match("^Listening on (.*)$", firstline) +if not match: + receiver.kill() + raise ValueError(f"Receiver returned unknown output: {firstline}") +receiver_port = int(match.group(1)) +firstline = str(receiver.stderr.readline(), "UTF-8") +match = re.match("^Listening on (.*)$", firstline) +if not match: + receiver.kill() + raise ValueError(f"Receiver returned unknown output: {firstline}") +receiver_port2 = int(match.group(1)) + +conn = p.external_devices.SpynnakerLiveSpikesConnection( + send_labels=[SEND_POP_LABEL], local_port=None) +conn.add_start_callback( + SEND_POP_LABEL, partial(send_spikes, WIDTH, HEIGHT, MIN_X, MIN_Y, + RUN_TIME / 1000.0)) + + +p.setup(1.0) +p.set_number_of_neurons_per_core(p.IF_curr_exp, + (PER_CORE_WIDTH, PER_CORE_HEIGHT)) +p.set_number_of_neurons_per_core(SpikeInjector, + (WIDTH, HEIGHT)) + +retina = p.Population( + WIDTH * HEIGHT, p.external_devices.SpikeInjector( + database_notify_port_num=conn.local_port), + structure=p.Grid2D(WIDTH / HEIGHT), label=SEND_POP_LABEL) + +target_pop = p.Population( + out_width * out_height, p.IF_curr_exp(), + structure=p.Grid2D(out_width / out_height), label=POP_LABEL) + +p.Projection(retina, target_pop, convolution, p.Convolution()) +p.external_devices.activate_live_output_for( + retina, database_notify_port_num=receiver_port) +p.external_devices.activate_live_output_for( + target_pop, database_notify_port_num=receiver_port2) + + +def do_run(): + global running + # target_pop.record("spikes") + p.external_devices.run_forever() + # spikes_by_time = defaultdict(list) + # for i, st in enumerate( + # target_pop.get_data("spikes").segments[0].spiketrains): + # for s in st.magnitude: + # spikes_by_time[s].append(i) + # for k, v in spikes_by_time.items(): + # print(f"{k}: {v}") + running = False + p.end() + + +t = Thread(target=do_run) +t.start() + + +def read_output(): + line = receiver.stderr.readline() + while line: + print(str(line, "UTF-8")) + line = receiver.stderr.readline() + + +r = Thread(target=read_output) +r.start() + +receiver.wait() +p.external_devices.request_stop() +t.join() diff --git a/pendulum/pendulum_follow_python_vis.py b/pendulum/pendulum_follow_python_vis.py new file mode 100644 index 0000000..8c08271 --- /dev/null +++ b/pendulum/pendulum_follow_python_vis.py @@ -0,0 +1,233 @@ +import math +from time import time, sleep +from functools import partial +from threading import Thread +from matplotlib import pyplot, colors +from matplotlib.patches import Rectangle +import numpy +import pyNN.spiNNaker as p +from spynnaker.pyNN.models.utility_models.spike_injector import SpikeInjector + +running = True + + +class CSVLine(): + def __init__(self, line): + if len(line) == 0: + raise EOFError + parts = [int(part.strip()) for part in line.split(",")] + if len(parts) < 4: + raise EOFError + self.x, self.y, self.p, send_time = parts + self.send_time = send_time / 1000.0 + + def __repr__(self): + return f"(x: {self.x}, y: {self.y}, send_time: {self.send_time})" + + def get_pos(self, min_x, min_y): + return self.x - min_x, self.y - min_y, self.send_time + + def get_spike(self, width, min_x, min_y): + return ((self.y - min_y) * width) + (self.x - min_x) + + +def make_kernel_circle(r, k_sz, weight, kernel): + var = int((k_sz+1)/2-1) + a = numpy.arange(0, 2 * math.pi, 0.01) + dx = numpy.round(r * numpy.sin(a)).astype("uint32") + dy = numpy.round(r * numpy.cos(a)).astype("uint32") + kernel[var + dx, var + dy] = weight + + + +def read_csv_line(f): + line = f.readline() + if not f: + return None + try: + return CSVLine(line) + except EOFError: + return None + + +def send_spikes(width, height, min_x, min_y, run_time, label, connection): + global running + start_time = None + max_x = min_x + width + max_y = min_y + height + with open("spikes.csv") as f: + first_time = -1 + line = read_csv_line(f) + while line and running: + send_time = line.send_time + if start_time is not None and send_time - start_time > run_time: + return + same_time_lines = [] + next_line = line + while next_line and next_line.send_time == send_time: + same_time_lines.append(next_line) + next_line = read_csv_line(f) + line = next_line + + filtered_lines = [ + ln for ln in same_time_lines + if (ln.x >= min_x and ln.x < max_x and ln.y >= min_y and + ln.y < max_y)] + + if not filtered_lines: + continue + + spikes = [s.get_spike(width, min_x, min_y) for s in filtered_lines] + spikes = spikes[:20] + + if first_time == -1: + first_time = send_time + start_time = time() + + sleep_time = (time() - start_time) - (send_time - first_time) + if sleep_time > 0: + sleep(sleep_time) + connection.send_spikes(label, spikes, send_full_keys=True) + running = False + + +WIDTH = 118 +HEIGHT = 118 +MIN_X = 450 +MIN_Y = 400 +PER_CORE_WIDTH = 16 +PER_CORE_HEIGHT = 16 +SPIF_IP = "spif-01" +SPIF_PORT = 3332 +POP_LABEL = "target" +SEND_POP_LABEL = "source" +RUN_TIME = 5000 +CHIP = (0, 0) + +scaler = 0.1 +k_sz = 39 +pos_w = 0.8 +neg_w = -1.0 + +kernel = numpy.zeros((k_sz, k_sz)) +make_kernel_circle(0.46*k_sz, k_sz, pos_w*scaler, kernel) +make_kernel_circle(0.41*k_sz, k_sz, neg_w*scaler, kernel) +make_kernel_circle(0.36*k_sz, k_sz, pos_w*scaler, kernel) +make_kernel_circle(0.26*k_sz, k_sz, neg_w*scaler, kernel) + +pyplot.imshow(kernel, interpolation='nearest') +pyplot.savefig("kernel.png") + +convolution = p.ConvolutionConnector(kernel_weights=kernel) +out_width, out_height = convolution.get_post_shape((WIDTH, HEIGHT)) + +print(f"Output {out_width} x {out_height}") + + +pyplot.ion() +colours = ["black", "g"] +cmap = colors.ListedColormap(colours) +image_data = numpy.zeros((WIDTH, HEIGHT)) +fig, axes = pyplot.subplots(figsize=(8, 8)) +plot = axes.imshow(image_data, interpolation="nearest", cmap="Greens", vmin=0, + vmax=100) +fig.canvas.draw() +fig.canvas.flush_events() +rect_pos = None +rect_count = None + +redraw = False + + +def recv(label, time, spikes): + global redraw, image_data + np_spikes = numpy.array(spikes) + ys, xs = numpy.divmod(np_spikes, WIDTH) + image_data[xs, ys] += 100 + redraw = True + + +def recv_conv(label, time, spikes): + global redraw, image_data, rect_pos, rect_count + print(f"{time}: {spikes}") + np_spikes = numpy.array(spikes) + square_row, rem = numpy.divmod(np_spikes, out_width * PER_CORE_WIDTH) + square_col, rem = numpy.divmod(rem, PER_CORE_WIDTH * PER_CORE_HEIGHT) + in_square_y, in_square_x = numpy.divmod(rem, PER_CORE_WIDTH) + ys = (k_sz//2) + square_col * PER_CORE_WIDTH + in_square_x + xs = (k_sz//2) + square_row * PER_CORE_HEIGHT + in_square_y + rect_pos = (numpy.amin(xs), numpy.amin(ys), numpy.amax(xs), numpy.amax(ys)) + rect_count = 4 + + +conn = p.external_devices.SpynnakerLiveSpikesConnection( + receive_labels=[SEND_POP_LABEL, POP_LABEL], send_labels=[SEND_POP_LABEL], local_port=None) +conn.add_receive_callback(SEND_POP_LABEL, recv) +conn.add_receive_callback(POP_LABEL, recv_conv) +conn.add_start_callback( + SEND_POP_LABEL, partial(send_spikes, WIDTH, HEIGHT, MIN_X, MIN_Y, + RUN_TIME / 1000.0)) + + +p.setup(1.0) +p.set_number_of_neurons_per_core(p.IF_curr_exp, + (PER_CORE_WIDTH, PER_CORE_HEIGHT)) +p.set_number_of_neurons_per_core(SpikeInjector, (WIDTH, HEIGHT)) + +retina = p.Population( + WIDTH * HEIGHT, p.external_devices.SpikeInjector( + database_notify_port_num=conn.local_port), + structure=p.Grid2D(WIDTH / HEIGHT), label=SEND_POP_LABEL) + +target_pop = p.Population( + out_width * out_height, p.IF_curr_exp(), + structure=p.Grid2D(out_width / out_height), label=POP_LABEL) + +p.Projection(retina, target_pop, convolution, p.Convolution()) +p.external_devices.activate_live_output_for( + retina, database_notify_port_num=conn.local_port) +p.external_devices.activate_live_output_for( + target_pop, database_notify_port_num=conn.local_port) + + +def do_run(): + global running + p.external_devices.run_forever() + running = False + p.end() + + +t = Thread(target=do_run) +t.start() + +rect = None +while running and fig.get_visible(): + try: + plot.set_array(image_data) + if rect_count is not None: + rect_count -= 1 + if rect_count == 0: + rect_pos = None + rect_count = None + if rect is not None: + rect.set_visible(False) + if rect_pos is not None: + x_min, y_min, x_max, y_max = rect_pos + width = x_max - x_min + 1 + height = y_max - y_min + 1 + if rect is None: + rect = Rectangle((x_min, y_min), width, height, linewidth=2, + edgecolor='r', facecolor='r') + axes.add_patch(rect) + else: + rect.set_visible(True) + rect.set_bounds(x_min, y_min, width, height) + fig.canvas.draw() + fig.canvas.flush_events() + image_data *= 0.5 + sleep(0.1) + except Exception: + break + +p.external_devices.request_stop() +t.join() diff --git a/pendulum/spike_filter.py b/pendulum/spike_filter.py new file mode 100644 index 0000000..ea2c757 --- /dev/null +++ b/pendulum/spike_filter.py @@ -0,0 +1,229 @@ +import numpy +import math +from time import time, sleep +from functools import partial +import pyNN.spiNNaker as p +from matplotlib import pyplot, colors +from matplotlib.patches import Rectangle +from spynnaker.pyNN.utilities.utility_calls import get_n_bits +from threading import Thread + +running = True + + +class CSVLine(): + def __init__(self, line): + if len(line) == 0: + raise EOFError + parts = [int(part.strip()) for part in line.split(",")] + if len(parts) < 4: + raise EOFError + self.x, self.y, self.p, send_time = parts + self.send_time = send_time / 1000.0 + + def __repr__(self): + return f"(x: {self.x}, y: {self.y}, send_time: {self.send_time})" + + def get_pos(self, min_x, min_y): + return self.x - min_x, self.y - min_y, self.send_time + + def get_spike(self, width, min_x, min_y): + return ((self.y - min_y) * width) + (self.x - min_x) + + +def make_kernel_circle(r, k_sz, weight, kernel): + var = int((k_sz+1)/2-1) + a = numpy.arange(0, 2 * math.pi, 0.01) + dx = numpy.round(r * numpy.sin(a)).astype("uint32") + dy = numpy.round(r * numpy.cos(a)).astype("uint32") + kernel[var + dx, var + dy] = weight + + + +def read_csv_line(f): + line = f.readline() + if not f: + return None + try: + return CSVLine(line) + except EOFError: + return None + + +def send_spikes(width, height, min_x, min_y, run_time, label, connection): + global running + start_time = None + max_x = min_x + width + max_y = min_y + height + y_shift = get_n_bits(width) + with open("spikes.csv") as f: + first_time = -1 + line = read_csv_line(f) + while line and running: + send_time = line.send_time + if start_time is not None and send_time - start_time > run_time: + return + same_time_lines = [] + next_line = line + while next_line and next_line.send_time == send_time: + same_time_lines.append(next_line) + next_line = read_csv_line(f) + line = next_line + + filtered_lines = [ + l for l in same_time_lines + if (l.x >= min_x and l.x < max_x and l.y >= min_y and + l.y < max_y)] + + if not filtered_lines: + continue + + spikes = [s.get_spike(width, min_x, min_y) for s in filtered_lines] + spikes = spikes[:20] + + if first_time == -1: + first_time = send_time + start_time = time() + + sleep_time = (time() - start_time) - (send_time - first_time) + if sleep_time > 0: + sleep(sleep_time) + connection.send_spikes(label, spikes, send_full_keys=True) + running = False + + +WIDTH = 120 +HEIGHT = 120 +MIN_X = 450 +MIN_Y = 400 +PER_CORE_WIDTH = 16 +PER_CORE_HEIGHT = 16 +SPIF_IP = "spif-01" +SPIF_PORT = 3332 +POP_LABEL = "target" +SEND_POP_LABEL = "source" +RUN_TIME = 5000 +CHIP = (0, 0) + +scaler = 0.1 +k_sz = 39 +pos_w = 0.8 +neg_w = -1.0 + +kernel = numpy.zeros((k_sz, k_sz)) +make_kernel_circle(0.46*k_sz, k_sz, pos_w*scaler, kernel) +make_kernel_circle(0.41*k_sz, k_sz, neg_w*scaler, kernel) +make_kernel_circle(0.36*k_sz, k_sz, pos_w*scaler, kernel) +make_kernel_circle(0.26*k_sz, k_sz, neg_w*scaler, kernel) + +pyplot.imshow(kernel, interpolation='nearest') +pyplot.savefig("kernel.png") + +convolution = p.ConvolutionConnector(kernel_weights=kernel) +out_width, out_height = convolution.get_post_shape((WIDTH, HEIGHT)) + +print(f"Output {out_width} x {out_height}") + + +pyplot.ion() +colours = ["black", "g"] +cmap = colors.ListedColormap(colours) +image_data = numpy.zeros((WIDTH, HEIGHT)) +fig, axes = pyplot.subplots(figsize=(8, 8)) +plot = axes.imshow(image_data, interpolation="nearest", cmap="Greens", vmin=0, + vmax=100) +fig.canvas.draw() +fig.canvas.flush_events() +rect_pos = None +rect_count = None + +redraw = False + + +def recv(label, time, spikes): + global redraw, image_data + np_spikes = numpy.array(spikes) + ys, xs = numpy.divmod(np_spikes, WIDTH) + image_data[xs, ys] += 100 + redraw = True + + +def recv_conv(label, time, spikes): + global redraw, image_data, rect_pos, rect_count + np_spikes = numpy.array(spikes) + square_row, rem = numpy.divmod(np_spikes, out_width * PER_CORE_WIDTH) + square_col, rem = numpy.divmod(rem, PER_CORE_WIDTH * PER_CORE_HEIGHT) + in_square_y, in_square_x = numpy.divmod(rem, PER_CORE_WIDTH) + xs = (k_sz//2) + square_row * PER_CORE_HEIGHT + in_square_x + ys = (k_sz//2) + square_col * PER_CORE_WIDTH + in_square_y + rect_pos = (numpy.amin(xs), numpy.amin(ys), numpy.amax(xs), numpy.amax(ys)) + rect_count = 4 + + +conn = p.external_devices.SpynnakerLiveSpikesConnection( + receive_labels=[SEND_POP_LABEL, POP_LABEL], send_labels=[SEND_POP_LABEL], local_port=None) +conn.add_receive_callback(SEND_POP_LABEL, recv) +conn.add_receive_callback(POP_LABEL, recv_conv) +conn.add_start_callback( + SEND_POP_LABEL, partial(send_spikes, WIDTH, HEIGHT, MIN_X, MIN_Y, RUN_TIME / 1000.0)) + + +p.setup(1.0) +p.set_number_of_neurons_per_core(p.IF_curr_exp, + (PER_CORE_WIDTH, PER_CORE_HEIGHT)) + +retina = p.Population( + WIDTH * HEIGHT, p.external_devices.SpikeInjector(), + structure=p.Grid2D(WIDTH / HEIGHT), label=SEND_POP_LABEL) + +target_pop = p.Population( + out_width * out_height, p.IF_curr_exp(), + structure=p.Grid2D(out_width / out_height), label=POP_LABEL) + +p.Projection(retina, target_pop, convolution, p.Convolution()) +p.external_devices.activate_live_output_for( + retina, database_notify_port_num=conn.local_port) +p.external_devices.activate_live_output_for( + target_pop, database_notify_port_num=conn.local_port) + + +def do_run(): + global running + p.external_devices.run_forever() + running = False + p.end() + + +t = Thread(target=do_run) +t.start() + +rect = None +while running and fig.get_visible(): + try: + plot.set_array(image_data) + if rect_count is not None: + rect_count -= 1 + if rect_count == 0: + rect_pos = None + rect_count = None + rect.set_visible(False) + if rect_pos is not None: + x_min, y_min, x_max, y_max = rect_pos + width = x_max - x_min + 1 + height = y_max - y_min + 1 + if rect is None: + rect = Rectangle((x_min, y_min), width, height, linewidth=2, + edgecolor='r', facecolor='r') + axes.add_patch(rect) + else: + rect.set_visible(True) + rect.set_bounds(x_min, y_min, width, height) + fig.canvas.draw() + fig.canvas.flush_events() + image_data *= 0.5 + sleep(0.1) + except Exception: + break + +p.external_devices.request_stop() +t.join() diff --git a/pendulum/spynnaker.cfg b/pendulum/spynnaker.cfg new file mode 100644 index 0000000..137a863 --- /dev/null +++ b/pendulum/spynnaker.cfg @@ -0,0 +1,2 @@ +[Simulation] +drop_late_spikes = False diff --git a/spiNNaker_start/.gitignore b/spiNNaker_start/.gitignore new file mode 100644 index 0000000..20d98d7 --- /dev/null +++ b/spiNNaker_start/.gitignore @@ -0,0 +1 @@ +/record/ diff --git a/spiNNaker_start/spinnaker_start.py b/spiNNaker_start/spinnaker_start.py new file mode 100644 index 0000000..7a8c994 --- /dev/null +++ b/spiNNaker_start/spinnaker_start.py @@ -0,0 +1,704 @@ +from __future__ import print_function +from six import iteritems +from threading import Thread, RLock, Condition +from matplotlib import pyplot, animation +from numpy.random.mtrand import shuffle +import functools +import numpy +import matplotlib +import time +import operator +import struct +import six +import sys +import logging +import pickle +import traceback + +from spinnman.constants import ROUTER_REGISTER_P2P_ADDRESS,\ + SYSTEM_VARIABLE_BASE_ADDRESS, address_length_dtype +from spinnman.processes import AbstractMultiConnectionProcess +from spinnman.messages.scp.impl import ReadMemory, GetChipInfo +from spinnman.model import P2PTable +from spinnman.processes.get_version_process import GetVersionProcess +from spinnman.messages.sdp.sdp_flag import SDPFlag +from spinnman.messages.scp.impl.read_memory import _SCPReadMemoryResponse +from spinnman.messages.spinnaker_boot import SystemVariableDefinition +from spinnman.connections.udp_packet_connections \ + import SCAMPConnection, BootConnection +from spinnman.processes import RoundRobinConnectionSelector +from spinnman.messages.scp import SCPRequestHeader +from spinnman.messages.scp.abstract_messages import AbstractSCPRequest +from spinnman.messages.scp.enums import SCPCommand +from spinnman.messages.sdp import SDPHeader +from spinnman.messages.scp.impl.get_version_response import GetVersionResponse +from spinnman.messages.spinnaker_boot import SpinnakerBootMessages + +from spinn_utilities.overrides import overrides + +from spalloc.job import Job +from spalloc.states import JobState + +from spinn_machine.machine import Machine + +print_lock = RLock() + +file_open_lock = Condition() +n_open_files = 0 + + +def warn(*args): + with print_lock: + print(*args) + + +def open_file(filename, mode): + global file_open_lock, n_open_files + with file_open_lock: + while n_open_files >= 200: + file_open_lock.wait() + n_open_files += 1 + return open(filename, mode) + + +def close_file(open_file): + global file_open_lock, n_open_files + with file_open_lock: + open_file.close() + n_open_files -= 1 + file_open_lock.notify_all() + + +def write_data_to_file(write_file, data_list): + write_file.write(struct.pack(" 0: + time.sleep(time_to_sleep) + callback(response) + else: + while not self._done: + self._send_request( + ReadSV(self._x, self._y, + SystemVariableDefinition.netinit_phase), + callback=self._process_netinit_phase_response) + self._finish() + time.sleep(0.1) + if self._save: + write_file = open_file( + "record/netinit_{}_{}.dat".format(self._x, self._y), "wb") + write_data_to_file(write_file, self._p2p_active_data) + write_data_to_file(write_file, self._netinit_phase_data) + close_file(write_file) + + +class GetP2PTableProcess(AbstractMultiConnectionProcess): + + def __init__(self, connection_selector, width, height, save, load): + super(GetP2PTableProcess, self).__init__(connection_selector) + self._width = width + self._height = height + self._p2p_column_data = [None] * width + self._save = save + self._load = load + + if load: + p2p_data = open_file("record/p2p.dat", "rb") + for column in range(width): + col_length = struct.unpack(" 0: + time.sleep(sleep_time) + self._process_chip_info(b_x, b_y, n_cores) + return + + # Get the set of chips to read + chips = [((x + self._eth_x) % self._width, + (y + self._eth_y) % self._height) + for x in range(0, 8) for y in range(0, 8) + if (x, y) not in Machine.BOARD_48_CHIP_GAPS] + chips = filter( + lambda coords: self._p2p_table.is_route(coords[0], coords[1]), + chips) + shuffle(chips) + + # Get the chip information for each chip + for (x, y) in chips: + self._send_request(GetChipInfo(x, y), self._receive_chip_info) + self._finish() + try: + self.check_for_error() + except Exception as e: + warn(e) + if self._save: + write_file = open_file( + "record/board_{}_{}.dat".format( + self._eth_x, self._eth_y), "wb") + write_data_to_file(write_file, self._data) + close_file(write_file) + + +class CoreCounter(object): + + def __init__(self, width, height): + self._total_cores = 0 + self._update_lock = RLock() + self._ready = False + self._notify_lock = Condition() + + self._width = width + self._height = height + self._image_data = numpy.zeros((height, width, 3), dtype="uint8") + self._ax = None + self._text = None + self._fig = None + self._max_value = [175, 150, 125, 100] + + def run(self): + matplotlib.rcParams['toolbar'] = 'None' + self._fig, self._ax = pyplot.subplots() + self._fig.canvas.set_window_title("SpiNNaker") + self._image = self._ax.imshow( + self._image_data, origin="lower") + self._text = self._ax.text( + self._width // 2, self._height // 2, "0,000,000", + ha="center", va="center", color="#FFFFFF", fontsize=40) + self._text.set_alpha(0.9) + self._ani = animation.FuncAnimation( + self._fig, self._update, interval=40, blit=True) + pyplot.subplots_adjust(0.05, 0.05, 1.0, 1.0) + self._fig.canvas.mpl_connect('key_release_event', self._key_press) + self._fig.canvas.mpl_connect('close_event', self._close) + pyplot.show() + + def _close(self, _event): + with self._notify_lock: + self._ready = True + self._notify_lock.notify_all() + + def _key_press(self, _event): + with self._notify_lock: + self._ready = True + self._notify_lock.notify_all() + + def wait_until_ready(self): + with self._notify_lock: + while not self._ready: + self._notify_lock.wait() + + def _update(self, _frame): + self._image.set_array(self._image_data) + bbox = self._ax.get_window_extent().transformed( + self._fig.dpi_scale_trans.inverted()) + self._text.set_fontsize(bbox.width * 12.5) + self._text.set_text("{:08,d}".format(self._total_cores)) + return [self._image, self._text] + + def _get_max_value(self, x, y): + index = 0 + if (x, y) == (0, 0): + index = 0 + elif (x % 8) == 0 and (y % 8) == 0: + index = 3 + elif (x % 8) == 0: + index = 1 + elif (y % 8) == 0: + index = 2 + return self._max_value[index] + + def add_ethernet(self, x, y): + colour = self._get_max_value(x, y) + self._image_data[y, x] = [colour, 0, 0] + + def set_ethernet_responding(self, x, y): + colour = self._get_max_value(x, y) + self._image_data[y, x] = [colour, colour, 0] + + def set_ethernet_booted(self, x, y): + colour = self._get_max_value(x, y) + self._image_data[y, x] = [colour, colour, 0] + + def set_ethernet_netinit_phase(self, x, y, phase): + colour = self._get_max_value(x, y) + self._image_data[y, x] = [colour, colour, phase] + + def set_ethernet_n_routes(self, x, y, n_routes): + colour = self._get_max_value(x, y) + max_n_routes = self._width * self._height + value = int(round((float(colour) / max_n_routes) * n_routes)) + self._image_data[y, x] = [255 - value, 0, 255 - value] + + def add_cores(self, eth_x, eth_y, x, y, n_cores): + colour = self._get_max_value(eth_x, eth_y) + with self._update_lock: + self._total_cores += n_cores + value = int(round((float(colour) / 18.0) * n_cores)) + self._image_data[y, x] = [0, value, 0] + + +class MainThread(object): + def __init__(self, core_counter, job, save, load): + self._done = False + self._thread = Thread( + target=self.run, args=[core_counter, job, save, load]) + self._close_lock = RLock() + self._boot_threads = list() + self._processes = list() + + def start(self): + self._thread.start() + + def join(self): + self._thread.join() + + def close(self): + with self._close_lock: + self._done = True + for thread in self._boot_threads: + thread.close() + + def run(self, core_counter, job, save, load): + job_connections = list() + for (x, y), ip_address in iteritems(job.connections): + job_connections.append((x, y, ip_address)) + job_connections.sort(key=operator.itemgetter(0, 1)) + with job: + warn("Waiting for user to start process") + core_counter.wait_until_ready() + warn("Process starting") + + # Get a list of connections to the machine and start a thread for + # each listening for the boot to be done + connections = list() + root_connection = None + boot_connection = None + with self._close_lock: + if not self._done: + for x, y, ip_address in job_connections: + connection = None + connection = SCAMPConnection( + x, y, remote_host=ip_address) + connections.append(connection) + core_counter.add_ethernet(x, y) + if (x, y) == (0, 0): + root_connection = connection + if not load: + boot_connection = BootConnection( + remote_host=ip_address) + reader = ReadNetinitPhaseProcess( + x, y, RoundRobinConnectionSelector([connection]), + core_counter, save, load) + reader.start() + self._boot_threads.append(reader) + + # Connect to the machine and boot it + boot_done = False + if load: + boot_done = True + tries = 3 + while not self._done and not boot_done and tries > 0: + warn("Booting machine", boot_connection.remote_ip_address) + boot_messages = SpinnakerBootMessages(board_version=5) + for boot_message in boot_messages.messages: + boot_connection.send_boot_message(boot_message) + time.sleep(2.0) + try: + warn("Waiting for boot to complete") + version_read_ok = False + while not boot_done and not self._done: + try: + get_version = GetVersionProcess( + RoundRobinConnectionSelector( + [root_connection])) + version = get_version.get_version(0, 0, 0) + version_read_ok = True + core_counter.set_ethernet_booted(0, 0) + if (version.x != + AbstractSCPRequest.DEFAULT_DEST_X_COORD and + version.y != + AbstractSCPRequest.DEFAULT_DEST_Y_COORD): + boot_done = True + core_counter.set_ethernet_booted(0, 0) + else: + time.sleep(1.0) + except Exception: + if not version_read_ok: + six.reraise(*sys.exc_info()) + except Exception: + warn("Boot failed, retrying") + tries -= 1 + if not boot_done and not self._done: + raise Exception("Could not boot machine") + + for thread in self._boot_threads: + thread.join() + + # Read the P2P table to know which chips should exist + if boot_done: + warn("Reading P2P Table") + p2p_process = GetP2PTableProcess( + RoundRobinConnectionSelector( + [root_connection]), job.width, job.height, save, load) + p2p_table = p2p_process.get_p2p_table() + + # Create a reader thread for each connection, + # and read the cores + for connection in connections: + process = ReadBoardProcess( + connection.chip_x, connection.chip_y, + job.width, job.height, p2p_table, + RoundRobinConnectionSelector([connection]), + core_counter, save, load) + process.start() + self._processes.append(process) + + # Wait for everything to finish + for process in self._processes: + process.join() + + +class MockJob(object): + def __init__(self, width, height): + self._boards = list() + self._height = height + self._width = width + + def add_board(self, x, y): + self._boards.append((x, y)) + + def __enter__(self): + return self + + def __exit__(self, _type, _value, _traceback): + return False + + @property + def n_boards(self): + return len(self._boards) + + @property + def width(self): + return self._width + + @property + def height(self): + return self._height + + @property + def connections(self): + return {(x, y): "127.0.0.1" for (x, y) in self._boards} + + def destroy(self): + pass + + def wait_for_state_change(self, state): + pass + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + + save = False + load = False + if len(sys.argv) > 1: + if sys.argv[1] == "--save": + save = True + elif sys.argv[1] == "--load": + load = True + + job = None + if load: + load_file = open_file("record/job.dat", "rb") + width, height, n_boards = struct.unpack(" cell[x][y] +init = puzzles[puzzle] + +# Dream problem - no input! +# init = [[0 for x in range(9)] for y in range(9)] +corr = init + +p.set_number_of_neurons_per_core(p.IF_curr_exp, 200) +p.set_number_of_neurons_per_core(p.SpikeSourcePoisson, 200) + +# +# set up the 9x9 cell array populations +# +cell_params_lif = { + 'cm': 0.25, # nF membrane capacitance + 'i_offset': 0.5, # nA bias current + 'tau_m': 20.0, # ms membrane time constant + 'tau_refrac': 2.0, # ms refractory period + 'tau_syn_E': 5.0, # ms excitatory synapse time constant + 'tau_syn_I': 5.0, # ms inhibitory synapse time constant + 'v_reset': -70.0, # mV reset membrane potential + 'v_rest': -65.0, # mV rest membrane potential + 'v_thresh': -50.0, # mV firing threshold voltage +} + +print("Creating Populations...") +cells = p.Population(n_total, p.IF_curr_exp, cell_params_lif, label="Cells", + additional_parameters={"spikes_per_second": 200}) +# cells.record("spikes") +ext.activate_live_output_for(cells, database_notify_port_num=vis_port) + +# +# add a noise source to each cell +# +print("Creating Noise Sources...") +default_rate = 35.0 +max_rate = 200.0 +rates = get_rates(init, n_total, n_cell, n_N, default_rate, max_rate) +noise = p.Population( + n_total, p.SpikeSourcePoisson, + {"rate": rates}, + label="Noise") + +p.Projection(noise, cells, p.OneToOneConnector(), + synapse_type=p.StaticSynapse(weight=weight_nois)) + +set_window = subprocess.Popen((sys.executable, "-m", "set_numbers", + str(n_total), str(n_cell), str(n_N), + str(default_rate), str(max_rate), str(puzzle)), + stdout=subprocess.PIPE) +firstline = str(set_window.stdout.readline(), "UTF-8") +match = re.match("^Listening on (.*)$", firstline) +if not match: + set_window.kill() + vis_process.kill() + raise ValueError(f"Receiver returned unknown output: {firstline}") +set_port = int(match.group(1)) + +p.external_devices.add_poisson_live_rate_control( + noise, database_notify_port_num=set_port) + + +# +# set up the cell internal inhibitory connections +# +print("Setting up cell inhibition...") +connections = list() +for x in range(9): + for y in range(9): + base = ((y * 9) + x) * n_cell + + # full constant matrix of weight_cell apart from n_N squares on + # diagonal + connections_cell = [ + (i + base, j + base, + weight_cell, delay) + for i in range(n_cell) for j in range(n_cell) + if i // n_N != j // n_N + ] + connections.extend(connections_cell) + + +# +# set up the inter-cell inhibitory connections +# +def interCell(ic_x, ic_y, ic_r, ic_c, conns): + """ Inhibit same number: connections are n_N squares on diagonal of + weight_cell() from cell[ic_x][ic_y] to cell[ic_r][ic_c] + """ + base_source = ((ic_y * 9) + ic_x) * n_cell + base_dest = ((ic_c * 9) + ic_r) * n_cell + # p.Projection(cells_pop[base_source:base_source+n_cell], + # cells_pop[base_dest:base_dest+n_cell], + # p.AllToAllConnector(), + # p.StaticSynapse(weight=weight_cell, delay=delay)) + connections_intC = [ + (i + base_source, j + base_dest, weight_cell, delay) + for i in range(n_cell) + for j in range(n_N * (i // n_N), n_N * (i // n_N + 1))] + + conns.extend(connections_intC) + + +print("Setting up inhibition between cells...") +for x in range(9): + for y in range(9): + for r in range(9): + if r != x: + interCell(x, y, r, y, connections) # by row... + for c in range(9): + if c != y: + interCell(x, y, x, c, connections) # by column... + for r in range(3 * (x // 3), 3 * (x // 3 + 1)): + for c in range(3 * (y // 3), 3 * (y // 3 + 1)): + if r != x and c != y: + interCell(x, y, r, c, connections) # & by square +conn_intC = p.FromListConnector(connections) +p.Projection(cells, cells, conn_intC, receptor_type="inhibitory") + +# initialise the network, run, and get results +cells.initialize(v=RandomDistribution("uniform", [-65.0, -55.0])) + + +def wait_for_end(): + set_window.wait() + set_window.terminate() + vis_process.terminate() + p.external_devices.request_stop() + + +wait_thread = Thread(target=wait_for_end) +wait_thread.start() + +p.external_devices.run_forever() + +# spikes = cells.getSpikes() +# f, axarr = pylab.subplots(9, 9) +# for y in range(9): +# for x in range(9): +# base = ((y * 9) + x) * n_cell +# next_base = base + n_cell +# ids = spikes[:, 0] +# cell_spikes = spikes[numpy.where((ids >= base) & (ids < next_base))] +# axarr[8 - y][x].plot( +# [i[1] for i in cell_spikes], +# [i[0] - base for i in cell_spikes], ".") +# axarr[8 - y][x].axis([0, run_time, -1, n_cell + 1]) +# # axarr[8 - y][x].axis('off') +# pylab.show() +# pylab.savefig("sudoku.png") + +p.end() diff --git a/sudoku/sudoku_osx b/sudoku/sudoku_osx new file mode 100755 index 0000000..9b3368b Binary files /dev/null and b/sudoku/sudoku_osx differ diff --git a/sudoku/utils.py b/sudoku/utils.py new file mode 100644 index 0000000..bb1bf97 --- /dev/null +++ b/sudoku/utils.py @@ -0,0 +1,101 @@ +puzzles = list() +puzzles.append( + # Diabolical problem: + [[0, 0, 1, 0, 0, 8, 0, 7, 3], + [0, 0, 5, 6, 0, 0, 0, 0, 1], + [7, 0, 0, 0, 0, 1, 0, 0, 0], + + [0, 9, 0, 8, 1, 0, 0, 0, 0], + [5, 3, 0, 0, 0, 0, 0, 4, 6], + [0, 0, 0, 0, 6, 5, 0, 3, 0], + + [0, 0, 0, 1, 0, 0, 0, 0, 4], + [8, 0, 0, 0, 0, 9, 3, 0, 0], + [9, 4, 0, 5, 0, 0, 7, 0, 0]]) +puzzles.append( + [[2, 0, 0, 0, 0, 6, 0, 3, 0], + [4, 8, 0, 0, 1, 9, 0, 0, 0], + [0, 0, 7, 0, 2, 0, 9, 0, 0], + + [0, 0, 0, 3, 0, 0, 0, 9, 0], + [7, 0, 8, 0, 0, 0, 1, 0, 5], + [0, 4, 0, 0, 0, 7, 0, 0, 0], + + [0, 0, 4, 0, 9, 0, 6, 0, 0], + [0, 0, 0, 6, 4, 0, 0, 1, 9], + [0, 5, 0, 1, 0, 0, 0, 0, 8]]) +puzzles.append( + [[0, 0, 3, 2, 0, 0, 0, 7, 0], + [0, 0, 5, 0, 0, 0, 3, 0, 0], + [0, 0, 8, 9, 7, 0, 0, 5, 0], + + [0, 0, 0, 8, 9, 0, 0, 0, 0], + [0, 5, 0, 0, 0, 0, 0, 2, 0], + [0, 0, 0, 0, 6, 1, 0, 0, 0], + + [0, 1, 0, 0, 2, 5, 6, 0, 0], + [0, 0, 4, 0, 0, 0, 8, 0, 0], + [0, 9, 0, 0, 0, 7, 5, 0, 0]]) +puzzles.append( + [[0, 1, 0, 0, 0, 0, 0, 0, 2], + [8, 7, 0, 0, 0, 0, 5, 0, 4], + [5, 0, 2, 0, 0, 0, 0, 9, 0], + + [0, 5, 0, 4, 0, 9, 0, 0, 1], + [0, 0, 0, 7, 3, 2, 0, 0, 0], + [9, 0, 0, 5, 0, 1, 0, 4, 0], + + [0, 2, 0, 0, 0, 0, 4, 0, 8], + [4, 0, 6, 0, 0, 0, 0, 1, 3], + [1, 0, 0, 0, 0, 0, 0, 2, 0]]) +puzzles.append( + [[8, 9, 0, 2, 0, 0, 0, 7, 0], + [0, 0, 0, 0, 8, 0, 0, 0, 0], + [0, 4, 1, 0, 3, 0, 5, 0, 0], + + [2, 5, 8, 0, 0, 0, 0, 0, 6], + [0, 0, 0, 0, 0, 0, 0, 0, 0], + [6, 0, 0, 0, 0, 0, 1, 4, 7], + + [0, 0, 7, 0, 1, 0, 4, 3, 0], + [0, 0, 0, 0, 2, 0, 0, 0, 0], + [0, 2, 0, 0, 0, 7, 0, 5, 1]]) +puzzles.append( + # "World's hardest sudoku": + # http://www.telegraph.co.uk/news/science/science-news/9359579/\ + # Worlds-hardest-sudoku-can-you-crack-it.html + [[8, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 0, 3, 6, 0, 0, 0, 0, 0], + [0, 7, 0, 0, 9, 0, 2, 0, 0], + + [0, 5, 0, 0, 0, 7, 0, 0, 0], + [0, 0, 0, 0, 4, 5, 7, 0, 0], + [0, 0, 0, 1, 0, 0, 0, 3, 0], + + [0, 0, 1, 0, 0, 0, 0, 6, 8], + [0, 0, 8, 5, 0, 0, 0, 1, 0], + [0, 9, 0, 0, 0, 0, 4, 0, 0]]) +puzzles.append( + [[1, 0, 0, 4, 0, 0, 0, 0, 0], + [7, 0, 0, 5, 0, 0, 6, 0, 3], + [0, 0, 0, 0, 3, 0, 4, 2, 0], + + [0, 0, 9, 0, 0, 0, 0, 3, 5], + [0, 0, 0, 3, 0, 5, 0, 0, 0], + [6, 3, 0, 0, 0, 0, 1, 0, 0], + + [0, 2, 6, 0, 5, 0, 0, 0, 0], + [9, 0, 4, 0, 0, 6, 0, 0, 7], + [0, 0, 0, 0, 0, 8, 0, 0, 2]]) + + +def get_rates(values, n_total, n_cell, n_N, default_rate, max_rate): + rates = [default_rate] * n_total + for x in range(9): + for y in range(9): + if values[8 - y][x] != 0: + base = ((y * 9) + x) * n_cell + for j in range(n_N * (values[8 - y][x] - 1), + n_N * values[8 - y][x]): + rates[j + base] = max_rate + return rates diff --git a/synfire/__init__.py b/synfire/__init__.py new file mode 100644 index 0000000..6725518 --- /dev/null +++ b/synfire/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. diff --git a/synfire/synfire.py b/synfire/synfire.py new file mode 100644 index 0000000..56a9643 --- /dev/null +++ b/synfire/synfire.py @@ -0,0 +1,107 @@ +# Copyright (c) 2016 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Synfire chain example +""" +import matplotlib.pyplot as plt +import pyNN.spiNNaker as sim +from spynnaker.pyNN.utilities import neo_convertor + +# number of neurons in each population +n_neurons = 100 +n_populations = 10 +weights = 0.5 +delays = 17.0 +simtime = 1000 + +sim.setup(timestep=1.0, min_delay=1.0) + +spikeArray = {'spike_times': [[0]]} +stimulus = sim.Population(1, sim.SpikeSourceArray, spikeArray, + label='stimulus') + +chain_pops = [ + sim.Population(n_neurons, sim.IF_curr_exp, {}, label='chain_{}'.format(i)) + for i in range(n_populations) +] +for pop in chain_pops: + pop.record("spikes") + +connector = sim.FixedNumberPreConnector(10) +for i in range(n_populations): + sim.Projection(chain_pops[i], chain_pops[(i + 1) % n_populations], + connector, + synapse_type=sim.StaticSynapse(weight=weights, + delay=delays)) + +sim.Projection(stimulus, chain_pops[0], sim.AllToAllConnector(), + synapse_type=sim.StaticSynapse(weight=5.0)) + +sim.run(simtime) +# None PyNN method which is faster +# spikes = [pop.spinnaker_get_data("spikes") for pop in chain_pops] + +# Pynn method and support method +neos = [pop.get_data("spikes") for pop in chain_pops] +spikes = map(neo_convertor.convert_spikes, neos) + +sim.end() + + +try: + plt.figure() + plt.xlabel('Time (ms)') + plt.ylabel('Neuron') + plt.title('Spikes Sent By Chain') + offset = 0 + for pop_spikes in spikes: + plt.plot( + [i[1] for i in pop_spikes], + [i[0] + offset for i in pop_spikes], "." + ) + offset += n_neurons + plt.show() +except Exception as ex: + print(spikes) + raise ex + + # Way to plot the spikes without neo converter but without the colours + # try: + # import matplotlib.pyplot as plt + # import pyNN.utility.plotting as plotting + # spike_trains = [neo.segments[0].spiketrains for neo in neos] + # offset = 0 + # for spike_train_list in spike_trains: + # for spike_train in spike_train_list: + # spike_train.annotations["source_index"] += offset + # offset += n_neurons + # spike_trains = [ + # spike_train for spike_train_list in spike_trains + # for spike_train in spike_train_list] + # panel = plotting.Panel( + # spike_trains, + # yticks=True, markersize=2, xlim=(0, simtime), + # line_properties=[ + # {"color": colour} + # for i, colour in enumerate(colours)]) + # plotting.Figure( + # panel, title="Synfire Example", + # annotations="Simulated with {}".format(sim.name())) + # plt.show() + # except Exception as ex: + # print(ex) + # for neo in neos: + # print(neo.segments[0].spiketrains) + # print("====") diff --git a/synfire/synfire_collab.py b/synfire/synfire_collab.py new file mode 100644 index 0000000..1f53aa4 --- /dev/null +++ b/synfire/synfire_collab.py @@ -0,0 +1,79 @@ +# Copyright (c) 2017 The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +""" +Synfire chain example +""" +import matplotlib.pyplot as plt +import pyNN.spiNNaker as sim +from spynnaker.pyNN.utilities import neo_convertor + +# number of neurons in each population +n_neurons = 100 +n_populations = 10 +weights = 0.5 +delays = 17.0 +simtime = 1000 + +sim.setup(timestep=1.0, min_delay=1.0) + +spikeArray = {'spike_times': [[0]]} +stimulus = sim.Population(1, sim.SpikeSourceArray, spikeArray, + label='stimulus') + +chain_pops = [ + sim.Population(n_neurons, sim.IF_curr_exp, {}, label='chain_{}'.format(i)) + for i in range(n_populations) +] +for pop in chain_pops: + pop.record("spikes") + +connector = sim.FixedNumberPreConnector(10) +for i in range(n_populations): + sim.Projection(chain_pops[i], chain_pops[(i + 1) % n_populations], + connector, + synapse_type=sim.StaticSynapse(weight=weights, + delay=delays)) + +sim.Projection(stimulus, chain_pops[0], sim.AllToAllConnector(), + synapse_type=sim.StaticSynapse(weight=5.0)) + +sim.run(simtime) +# None PyNN method which is faster +# spikes = [pop.spinnaker_get_data("spikes") for pop in chain_pops] + +# Pynn method and support method +neos = [pop.get_data("spikes") for pop in chain_pops] +spikes = map(neo_convertor.convert_spikes, neos) + +sim.end() + + +try: + plt.figure() + plt.xlabel('Time (ms)') + plt.ylabel('Neuron') + plt.title('Spikes Sent By Chain') + offset = 0 + for pop_spikes in spikes: + plt.plot( + [i[1] for i in pop_spikes], + [i[0] + offset for i in pop_spikes], "." + ) + offset += n_neurons + plt.show() + # pylab.savefig("results.png") +except Exception as ex: + print(spikes) + raise ex