Skip to content

Commit

Permalink
merged in master
Browse files Browse the repository at this point in the history
  • Loading branch information
Christian-B committed Jun 15, 2023
2 parents 58a797a + a0c24a3 commit af6195d
Show file tree
Hide file tree
Showing 27 changed files with 269 additions and 218 deletions.
4 changes: 2 additions & 2 deletions spynnaker/pyNN/models/common/param_generator_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def param_generator_params(values):
Get the parameter generator parameters as a numpy array.
:param values:
:type values: int or ~pyNN.random.NumpyRNG
:type values: int or ~pyNN.random.RandomDistribution
:rtype: ~numpy.ndarray
"""
if numpy.isscalar(values):
Expand Down Expand Up @@ -137,7 +137,7 @@ def param_generator_params_size_in_bytes(values):
Get the size of the parameter generator parameters in bytes.
:param values:
:type values: int or ~pyNN.random.NumpyRNG
:type values: int or ~pyNN.random.RandomDistribution
:rtype: int
:raises TypeError: If `values` is of an unsupported data type
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,33 +52,27 @@ class AbstractConnector(object, metaclass=AbstractBase):
"_delays",
"__min_delay",
"__n_clipped_delays",
"_rng",
"__safe",
"__space",
"__verbose",
"_weights",
"__param_seeds",
"__synapse_info"]

def __init__(self, safe=True, callback=None, verbose=False, rng=None):
def __init__(self, safe=True, callback=None, verbose=False):
"""
:param bool safe: if True, check that weights and delays have valid
values. If False, this check is skipped. (NB: SpiNNaker always
checks.)
:param callable callback: Ignored
:param bool verbose:
:param rng:
Seeded random number generator, or None to make one when needed
:type rng: ~pyNN.random.NumpyRNG or None
"""
if callback is not None:
warn_once(logger, "sPyNNaker ignores connector callbacks.")
self.__safe = safe
self.__space = None
self.__verbose = verbose

self._rng = rng

self.__n_clipped_delays = numpy.int64(0)
self.__min_delay = 0
self.__param_seeds = dict()
Expand All @@ -98,16 +92,14 @@ def set_projection_information(self, synapse_info):
:param SynapseInformation synapse_info: the synapse info
"""
self._rng = (self._rng or NumpyRNG())
self.__min_delay = SpynnakerDataView.get_simulation_time_step_ms()

def _get_delay_minimum(self, delays, n_connections, synapse_info):
"""
Get the minimum delay given a float or RandomDistribution.
:param delays: the delays
:type delays: ~numpy.ndarray or ~spynnaker.pyNN.RandomDistribution
or int or float
:type delays: ~spynnaker.pyNN.RandomDistribution or int or float or str
:param int n_connections: how many connections
"""
if isinstance(delays, RandomDistribution):
Expand All @@ -132,7 +124,7 @@ def _get_delay_maximum(self, delays, n_connections, synapse_info):
Get the maximum delay given a float or RandomDistribution.
:param delays:
:type delays: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float
:type delays: ~pyNN.random.RandomDistribution or int or float or str
:param int n_connections:
"""
if isinstance(delays, RandomDistribution):
Expand Down Expand Up @@ -176,7 +168,7 @@ def get_delay_variance(self, delays, synapse_info):
Get the variance of the delays.
:param delays:
:type delays: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float
:type delays: ~~pyNN.random.RandomDistribution or int or float of str
:rtype: float
"""
if isinstance(delays, RandomDistribution):
Expand All @@ -196,8 +188,7 @@ def _get_n_connections_from_pre_vertex_with_delay_maximum(
max_delay given given a float, RandomDistribution or list of delays.
:param delays:
:type delays: ~numpy.ndarray or spynnaker.pyNN.RandomDistribution
or int or float
:type delays: spynnaker.pyNN.RandomDistribution or int or float or str
:param int n_total_connections:
:param int n_connections:
:param float min_delay:
Expand Down Expand Up @@ -244,7 +235,7 @@ def get_n_connections_from_pre_vertex_maximum(
(inclusive) if both specified (otherwise all connections).
:param delays:
:type delays: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float
:type delays: ~pyNN.random.RandomDistribution or int or float or str
:param int n_post_atoms:
:param SynapseInformation synapse_info:
:param min_delay:
Expand All @@ -269,7 +260,7 @@ def get_weight_mean(self, weights, synapse_info):
Get the mean of the weights.
:param weights:
:type weights: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float
:type weights: ~pyNN.random.RandomDistribution or int or float or str
:rtype: float
"""
if isinstance(weights, RandomDistribution):
Expand All @@ -286,7 +277,7 @@ def _get_weight_maximum(self, weights, n_connections, synapse_info):
Get the maximum of the weights.
:param weights:
:type weights: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float
:type weights: ~pyNN.random.RandomDistribution or int or float or str
:param int n_connections:
:rtype: float
"""
Expand Down Expand Up @@ -327,7 +318,7 @@ def get_weight_variance(self, weights, synapse_info):
Get the variance of the weights.
:param weights:
:type weights: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or float
:type weights: ~pyNN.random.RandomDistribution or int or float or str
:rtype: float
"""
if isinstance(weights, RandomDistribution):
Expand Down Expand Up @@ -371,7 +362,7 @@ def _get_distances(self, values, synapse_info):
def _generate_random_values(
self, values, n_connections, post_vertex_slice):
"""
:param ~pyNN.random.NumpyRNG values:
:param ~pyNN.random.RandomDistribution values:
:param int n_connections:
:param ~pacman.model.graphs.common.Slice post_vertex_slice:
:rtype: ~numpy.ndarray
Expand All @@ -394,7 +385,8 @@ def _generate_values(
synapse_info):
"""
:param values:
:type values: ~pyNN.random.NumpyRNG or int or float or str or callable
:type values: ~pyNN.random.RandomDistribution or int or float or str
or callable
:param int n_connections:
:param ~pacman.model.graphs.common.Slice post_slice:
:param SynapseInformation synapse_info:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import numpy
from spinn_utilities.abstract_base import abstractproperty, AbstractBase
from spinn_utilities.overrides import overrides
from spynnaker.pyNN.utilities import utility_calls
from spynnaker.pyNN.models.neural_projections.connectors import (
AbstractConnector)
from spynnaker.pyNN.exceptions import SynapticConfigurationException
Expand All @@ -25,6 +24,8 @@
param_generator_id, is_param_generatable)
from .abstract_generate_connector_on_host import (
AbstractGenerateConnectorOnHost)
from pyNN.random import RandomDistribution
from spynnaker.pyNN.utilities.utility_calls import check_rng


# Hashes of the connection generators supported by the synapse expander
Expand All @@ -44,18 +45,7 @@ class AbstractGenerateConnectorOnMachine(
Indicates that the connectivity can be generated on the machine.
"""

__slots__ = [
"__connector_seed"
]

def __init__(self, safe=True, callback=None, verbose=False):
"""
:param bool safe:
:param callable callback: Ignored
:param bool verbose:
"""
super().__init__(safe=safe, callback=callback, verbose=verbose)
self.__connector_seed = dict()
__slots__ = []

@overrides(AbstractConnector.validate_connection)
def validate_connection(self, application_edge, synapse_info):
Expand All @@ -68,20 +58,6 @@ def validate_connection(self, application_edge, synapse_info):
" generated on the machine, but the connector cannot"
" be generated on host!")

def _get_connector_seed(self, pre_vertex_slice, post_vertex_slice, rng):
"""
Get the seed of the connector for a given pre-post pairing.
:param ~pacman.model.graphs.common.Slice pre_vertex_slice:
:param ~pacman.model.graphs.common.Slice post_vertex_slice:
:param ~pyNN.random.NumpyRNG rng:
"""
key = (id(pre_vertex_slice), id(post_vertex_slice))
if key not in self.__connector_seed:
self.__connector_seed[key] = utility_calls.create_mars_kiss_seeds(
rng)
return self.__connector_seed[key]

def generate_on_machine(self, weights, delays):
"""
Determine if this instance can generate on the machine.
Expand All @@ -90,23 +66,28 @@ def generate_on_machine(self, weights, delays):
be generated on the machine
:param weights:
:type weights: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or
float or list(int) or list(float)
:type weights: ~numpy.ndarray or ~pyNN.random.RandomDistribution
or int or float or list(int) or list(float)
:param delays:
:type delays: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or
float or list(int) or list(float)
:type delays: ~numpy.ndarray or ~pyNN.random.RandomDistribution
or int or float or list(int) or list(float)
:rtype: bool
"""
return (is_param_generatable(weights) and
is_param_generatable(delays))
if (not is_param_generatable(weights) or
not is_param_generatable(delays)):
return False
if isinstance(weights, RandomDistribution):
check_rng(weights.rng, "RandomDistribution in weight")
if isinstance(delays, RandomDistribution):
check_rng(delays.rng, "RandomDistribution in delay")
return True

def gen_weights_id(self, weights):
"""
Get the id of the weight generator on the machine.
:param weights:
:type weights: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or
float or list(int) or list(float)
:type weights: ~pyNN.random.RandomDistribtuion or int or float
:rtype: int
"""
return param_generator_id(weights)
Expand All @@ -116,7 +97,7 @@ def gen_weights_params(self, weights):
Get the parameters of the weight generator on the machine.
:param weights:
:type weights: ~pyNN.random.NumpyRNG or int or float
:type weights: ~pyNN.random.RandomDistribution or int or float
:rtype: ~numpy.ndarray(~numpy.uint32)
"""
return param_generator_params(weights)
Expand All @@ -126,7 +107,7 @@ def gen_weight_params_size_in_bytes(self, weights):
The size of the weight parameters in bytes.
:param weights:
:type weights: ~pyNN.random.NumpyRNG or int or float
:type weights: ~pyNN.random.RandomDistribution or int or float
:rtype: int
"""
return param_generator_params_size_in_bytes(weights)
Expand All @@ -136,7 +117,7 @@ def gen_delays_id(self, delays):
Get the id of the delay generator on the machine.
:param delays:
:type delays: ~pyNN.random.NumpyRNG or int or float
:type delays: ~pyNN.random.RandomDistribution or int or float
:rtype: int
"""
return param_generator_id(delays)
Expand All @@ -146,7 +127,7 @@ def gen_delay_params(self, delays):
Get the parameters of the delay generator on the machine.
:param delays:
:type delays: ~pyNN.random.NumpyRNG or int or float
:type delays: ~pyNN.random.RandomDistribution or int or float
:rtype: ~numpy.ndarray(~numpy.uint32)
"""
return param_generator_params(delays)
Expand All @@ -156,8 +137,7 @@ def gen_delay_params_size_in_bytes(self, delays):
The size of the delay parameters in bytes.
:param delays:
:type delays: ~numpy.ndarray or ~pyNN.random.NumpyRNG or int or
float or list(int) or list(float)
:type delays: ~pyNN.random.RandomDistribution or int or float
:rtype: int
"""
return param_generator_params_size_in_bytes(delays)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
arccos, arcsin, arctan, arctan2, ceil, cos, cosh, exp, fabs, floor, fmod,
hypot, ldexp, log, log10, modf, power, sin, sinh, sqrt, tan, tanh, maximum,
minimum, e, pi)
from pyNN.random import NumpyRNG
from spinn_utilities.overrides import overrides
from spinn_utilities.safe_eval import SafeEval
from spynnaker.pyNN.utilities.utility_calls import (
Expand All @@ -42,7 +43,8 @@ class DistanceDependentProbabilityConnector(
__slots__ = [
"__allow_self_connections",
"__d_expression",
"__probs"]
"__probs",
"__rng"]

def __init__(
self, d_expression, allow_self_connections=True, safe=True,
Expand Down Expand Up @@ -81,7 +83,7 @@ def __init__(
super().__init__(safe, callback, verbose)
self.__d_expression = d_expression
self.__allow_self_connections = allow_self_connections
self._rng = rng
self.__rng = rng or NumpyRNG()
self.__probs = None
if n_connections is not None:
raise NotImplementedError(
Expand Down Expand Up @@ -179,7 +181,7 @@ def create_synaptic_block(
self, post_slices, post_vertex_slice, synapse_type, synapse_info):
probs = self.__probs[:, post_vertex_slice.as_slice].reshape(-1)
n_items = synapse_info.n_pre_neurons * post_vertex_slice.n_atoms
items = self._rng.next(n_items)
items = self.__rng.next(n_items)

# If self connections are not allowed, remove the possibility of
# self connections by setting them to a value of infinity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
# limitations under the License.
import math
import numpy
from pyNN.random import NumpyRNG
from spinn_utilities.overrides import overrides
from spinn_front_end_common.utilities.constants import BYTES_PER_WORD
from .abstract_connector import AbstractConnector
Expand All @@ -38,7 +39,8 @@ class FixedNumberPostConnector(AbstractGenerateConnectorOnMachine,
"__n_post",
"__post_neurons",
"__post_neurons_set",
"__with_replacement"]
"__with_replacement",
"__rng"]

def __init__(
self, n, allow_self_connections=True, safe=True, verbose=False,
Expand Down Expand Up @@ -79,7 +81,7 @@ def __init__(
self.__with_replacement = with_replacement
self.__post_neurons = None
self.__post_neurons_set = False
self._rng = rng
self.__rng = rng

def set_projection_information(self, synapse_info):
super().set_projection_information(synapse_info)
Expand Down Expand Up @@ -113,6 +115,7 @@ def _get_post_neurons(self, synapse_info):
:param SynapseInformation synapse_info:
:rtype: list(~numpy.ndarray)
"""
rng = self.__rng or NumpyRNG()
# If we haven't set the array up yet, do it now
if not self.__post_neurons_set:
self.__post_neurons = [None] * synapse_info.n_pre_neurons
Expand Down Expand Up @@ -148,11 +151,11 @@ def _get_post_neurons(self, synapse_info):
synapse_info.n_post_neurons)])

# Now use this list in the random choice
self.__post_neurons[m] = self._rng.choice(
self.__post_neurons[m] = rng.choice(
no_self_post_neurons, self.__n_post,
self.__with_replacement)
else:
self.__post_neurons[m] = self._rng.choice(
self.__post_neurons[m] = rng.choice(
synapse_info.n_post_neurons, self.__n_post,
self.__with_replacement)

Expand Down Expand Up @@ -305,3 +308,8 @@ def gen_connector_params(self):
AbstractGenerateConnectorOnMachine.gen_connector_params_size_in_bytes)
def gen_connector_params_size_in_bytes(self):
return 3 * BYTES_PER_WORD

@overrides(AbstractConnector.validate_connection)
def validate_connection(self, application_edge, synapse_info):
if self.generate_on_machine(synapse_info.weights, synapse_info.delays):
utility_calls.check_rng(self.__rng, "FixedNumberPostConnector")

0 comments on commit af6195d

Please sign in to comment.