Source code for spynnaker.pyNN.models.abstract_pynn_model

# 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.

from collections import defaultdict
import sys
import numpy
from pyNN import descriptions
from spinn_utilities.classproperty import classproperty
from spinn_utilities.abstract_base import (
    AbstractBase, abstractmethod, abstractproperty)
from spynnaker.pyNN.models.defaults import get_dict_from_init
from spynnaker.pyNN.exceptions import SpynnakerException


[docs] class AbstractPyNNModel(object, metaclass=AbstractBase): """ A Model that can be passed in to a Population object in PyNN. """ __slots__ = [] _max_atoms_per_core = defaultdict(lambda: None)
[docs] @classmethod def set_model_max_atoms_per_dimension_per_core(cls, n_atoms=None): """ Set the default maximum number of atoms per dimension per core for this model. This can be overridden by the individual Population. The new value can be `None`, meaning that the maximum is the same as the number of atoms, an int, meaning all Populations of this model must have one dimension, or a tuple of *n* integers, meaning all Populations of this model must have *n* dimensions. If not all Populations of this model have the same number of dimensions, it is recommended to set this to `None` here and then set the maximum on each Population. :param n_atoms: The new maximum, or `None` for the largest possible :type n_atoms: int or tuple or None """ abs_max = cls.absolute_max_atoms_per_core if n_atoms is not None and numpy.prod(n_atoms) > abs_max: raise SpynnakerException( "The absolute maximum neurons per core for this model is" f" {abs_max}") AbstractPyNNModel._max_atoms_per_core[cls] = n_atoms
[docs] @classmethod def get_model_max_atoms_per_dimension_per_core(cls): """ Get the maximum number of atoms per dimension per core for this model. :rtype: int or tuple or None """ # If there is a stored value, use it max_stored = AbstractPyNNModel._max_atoms_per_core.get(cls) if max_stored is not None: return max_stored # Otherwise return the absolute maximum return cls.absolute_max_atoms_per_core
@classproperty def absolute_max_atoms_per_core(cls): # pylint: disable=no-self-argument """ The absolute maximum number of atoms per core. This is an integer regardless of the number of dimensions in any vertex. :rtype: int """ return sys.maxsize @staticmethod def __get_init_params_and_svars(the_cls): init = getattr(the_cls, "__init__") while hasattr(init, "_method"): init = getattr(init, "_method") params = None if hasattr(init, "_parameters"): params = getattr(init, "_parameters") svars = None if hasattr(init, "_state_variables"): svars = getattr(init, "_state_variables") return init, params, svars @classproperty def default_parameters(cls): # pylint: disable=no-self-argument """ Get the default values for the parameters of the model. :rtype: dict(str, Any) """ init, params, svars = cls.__get_init_params_and_svars(cls) return get_dict_from_init(init, skip=svars, include=params) @classproperty def default_initial_values(cls): # pylint: disable=no-self-argument """ Get the default initial values for the state variables of the model. :rtype: dict(str, Any) """ init, params, svars = cls.__get_init_params_and_svars(cls) if params is None and svars is None: return {} return get_dict_from_init(init, skip=params, include=svars)
[docs] @classmethod def get_parameter_names(cls): """ Get the names of the parameters of the model. :rtype: list(str) """ return cls.default_parameters.keys() # pylint: disable=no-member
[docs] @classmethod def has_parameter(cls, name): """ Determine if the model has a parameter with the given name. :param str name: The name of the parameter to check for :rtype: bool """ return name in cls.default_parameters
@abstractproperty def default_population_parameters(self): """ The default values for the parameters at the population level. These are parameters that can be passed in to the Population constructor in addition to the standard PyNN options. :rtype: dict(str, Any) """
[docs] @abstractmethod def create_vertex(self, n_neurons, label): """ Create a vertex for a population of the model. :param int n_neurons: The number of neurons in the population :param str label: The label to give to the vertex :return: An application vertex for the population :rtype: PopulationApplicationVertex """
@property def name(self): """ The name of this model. :rtype: str """ return self.__class__.__name__
[docs] def describe(self, template='modeltype_default.txt', engine='default'): """ Returns a human-readable description of the population. The output may be customized by specifying a different template together with an associated template engine (see :mod:`pyNN.descriptions`). If ``template`` is ``None``, then a dictionary containing the template context will be returned. :param str template: Template filename :param engine: Template substitution engine :type engine: str or ~pyNN.descriptions.TemplateEngine or None :rtype: str or dict """ context = { "name": self.name } return descriptions.render(engine, template, context)