Esempio n. 1
0
    def __init__(self,
                 presynaptic_population,
                 postsynaptic_population,
                 label,
                 connector,
                 spinnaker_control,
                 machine_time_step,
                 timescale_factor,
                 source=None,
                 target='excitatory',
                 synapse_dynamics=None,
                 rng=None):
        """
        Instantiates a :py:object:`Projection`.
        """
        self._spinnaker = spinnaker_control
        self._projection_edge = None
        self._projection_list_ranges = None
        self._delay_edge = None
        self._delay_list_ranges = None
        self._host_based_synapse_list = None
        self._has_retrieved_synaptic_list_from_machine = False

        if isinstance(postsynaptic_population._get_vertex,
                      AbstractPopulationVertex):
            # Check that the "target" is an acceptable value
            targets = postsynaptic_population._get_vertex.get_synapse_targets()
            if target not in targets:
                raise exceptions.ConfigurationException(
                    "Target {} is not available in the post-synaptic "
                    "pynn_population.py (choices are {})".format(
                        target, targets))
            synapse_type = \
                postsynaptic_population._get_vertex.get_synapse_id(target)
        else:
            raise exceptions.ConfigurationException(
                "postsynaptic_population is not a supposal reciever of"
                " synaptic projections")

        self._weight_scale = postsynaptic_population._get_vertex.weight_scale
        synapse_list = \
            connector.generate_synapse_list(
                presynaptic_population, postsynaptic_population,
                1000.0 / machine_time_step,
                postsynaptic_population._get_vertex.weight_scale, synapse_type)
        self._host_based_synapse_list = copy.deepcopy(synapse_list)

        # If there are some negative weights
        if synapse_list.get_min_weight() < 0:

            # If there are mixed negative and positive weights,
            # raise an exception
            if synapse_list.get_max_weight() > 0:
                raise exceptions.ConfigurationException("Weights must be "
                                                        "positive")

            # Otherwise, the weights are all negative, so invert them(!)
            else:
                synapse_list.flip()

        # Set any weight scaling for STDP
        if synapse_dynamics is not None:
            synapse_dynamics.weight_scale =\
                postsynaptic_population._get_vertex.weight_scale

        # check if all delays requested can fit into the natively supported
        # delays in the models
        max_delay = synapse_list.get_max_delay()
        natively_supported_delay_for_models = \
            constants.MAX_SUPPORTED_DELAY_TICS

        delay_extention_max_supported_delay = \
            constants.MAX_DELAY_BLOCKS * \
            constants.MAX_TIMER_TICS_SUPPORTED_PER_BLOCK

        if max_delay > (natively_supported_delay_for_models +
                        delay_extention_max_supported_delay):
            raise exceptions.ConfigurationException(
                "the max delay for projection {} is not supported by the "
                "pacman toolchain".format(max_delay))

        if conf.config.has_option("Model", "max_delay"):
            user_max_delay = conf.config.get("Model", "max_delay")
            if max_delay > user_max_delay:
                logger.warn("The end user entered a max delay"
                            " for which the projection breaks")

        # check that the projection edges label is not none, and give an
        # autogenerated label if set to None
        if label is None:
            label = "projection edge {}".format(Projection._projection_count)
            Projection._projection_count += 1

        if max_delay > natively_supported_delay_for_models:
            source_sz = presynaptic_population._get_vertex.n_atoms
            self._add_delay_extension(source_sz, max_delay,
                                      natively_supported_delay_for_models,
                                      synapse_list, presynaptic_population,
                                      postsynaptic_population,
                                      machine_time_step, timescale_factor,
                                      label, synapse_dynamics)

        else:

            # Find out if there is an existing edge between the populations
            edge_to_merge = self._find_existing_edge(
                presynaptic_population._get_vertex,
                postsynaptic_population._get_vertex)
            if edge_to_merge is not None:

                # If there is an existing edge, merge the lists
                self._projection_list_ranges = \
                    edge_to_merge.synapse_list.merge(synapse_list)
                self._projection_edge = edge_to_merge
            else:

                # If there isn't an existing edge, create a new one
                self._projection_edge = ProjectionPartitionableEdge(
                    presynaptic_population,
                    postsynaptic_population,
                    machine_time_step,
                    synapse_list=synapse_list,
                    synapse_dynamics=synapse_dynamics,
                    label=label)

                # add edge to the graph
                spinnaker_control.add_edge(self._projection_edge)
                self._projection_list_ranges = synapse_list.ranges()
Esempio n. 2
0
    def __init__(self,
                 presynaptic_population,
                 postsynaptic_population,
                 label,
                 connector,
                 spinnaker_control,
                 machine_time_step,
                 user_max_delay,
                 timescale_factor,
                 source=None,
                 target='excitatory',
                 synapse_dynamics=None,
                 rng=None):
        self._spinnaker = spinnaker_control
        self._projection_edge = None
        self._host_based_synapse_list = None
        self._has_retrieved_synaptic_list_from_machine = False

        if not isinstance(postsynaptic_population._get_vertex,
                          AbstractPopulationVertex):

            raise exceptions.ConfigurationException(
                "postsynaptic population is not designed to receive"
                " synaptic projections")

        synapse_type = postsynaptic_population._get_vertex\
            .synapse_type.get_synapse_id_by_target(target)
        if synapse_type is None:
            raise exceptions.ConfigurationException(
                "Synapse target {} not found in {}".format(
                    target, postsynaptic_population.label))

        synapse_dynamics_stdp = None
        if synapse_dynamics is None:
            synapse_dynamics_stdp = SynapseDynamicsStatic()
        else:
            synapse_dynamics_stdp = synapse_dynamics.slow
        postsynaptic_population._get_vertex.synapse_dynamics = \
            synapse_dynamics_stdp

        # Set and store information for future processing
        self._synapse_information = SynapseInformation(connector,
                                                       synapse_dynamics_stdp,
                                                       synapse_type)
        connector.set_projection_information(presynaptic_population,
                                             postsynaptic_population, rng,
                                             machine_time_step)

        max_delay = synapse_dynamics_stdp.get_delay_maximum(connector)
        if max_delay is None:
            max_delay = user_max_delay

        # check if all delays requested can fit into the natively supported
        # delays in the models
        delay_extension_max_supported_delay = (
            constants.MAX_DELAY_BLOCKS *
            constants.MAX_TIMER_TICS_SUPPORTED_PER_BLOCK)
        post_vertex_max_supported_delay_ms = \
            postsynaptic_population._get_vertex.maximum_delay_supported_in_ms

        if max_delay > (post_vertex_max_supported_delay_ms +
                        delay_extension_max_supported_delay):
            raise exceptions.ConfigurationException(
                "The maximum delay {} for projection is not supported".format(
                    max_delay))

        if max_delay > (user_max_delay / (machine_time_step / 1000.0)):
            logger.warn("The end user entered a max delay"
                        " for which the projection breaks")

        # check that the projection edges label is not none, and give an
        # auto generated label if set to None
        if label is None:
            label = "projection edge {}".format(
                spinnaker_control.none_labelled_edge_count)
            spinnaker_control.increment_none_labelled_edge_count()

        # Find out if there is an existing edge between the populations
        edge_to_merge = self._find_existing_edge(
            presynaptic_population._get_vertex,
            postsynaptic_population._get_vertex)
        if edge_to_merge is not None:

            # If there is an existing edge, add the connector
            edge_to_merge.add_synapse_information(self._synapse_information)
            self._projection_edge = edge_to_merge
        else:

            # If there isn't an existing edge, create a new one
            self._projection_edge = ProjectionPartitionableEdge(
                presynaptic_population._get_vertex,
                postsynaptic_population._get_vertex,
                self._synapse_information,
                label=label)

            # add edge to the graph
            spinnaker_control.add_partitionable_edge(self._projection_edge,
                                                     EDGE_PARTITION_ID)

        # If the delay exceeds the post vertex delay, add a delay extension
        if max_delay > post_vertex_max_supported_delay_ms:
            delay_edge = self._add_delay_extension(
                presynaptic_population, postsynaptic_population, max_delay,
                post_vertex_max_supported_delay_ms, machine_time_step,
                timescale_factor)
            self._projection_edge.delay_edge = delay_edge
        spinnaker_control._add_projection(self)

        # If there is a virtual board, we need to hold the data in case the
        # user asks for it
        self._virtual_connection_list = None
        if spinnaker_control.use_virtual_board:
            self._virtual_connection_list = list()
            pre_vertex = presynaptic_population._get_vertex
            post_vertex = postsynaptic_population._get_vertex
            connection_holder = ConnectionHolder(None, False,
                                                 pre_vertex.n_atoms,
                                                 post_vertex.n_atoms,
                                                 self._virtual_connection_list)

            post_vertex.add_pre_run_connection_holder(
                connection_holder, self._projection_edge,
                self._synapse_information)
Esempio n. 3
0
    def _add_delay_extension(self, num_src_neurons, max_delay_for_projection,
                             max_delay_per_neuron, original_synapse_list,
                             presynaptic_population, postsynaptic_population,
                             machine_time_step, timescale_factor, label,
                             synapse_dynamics):
        """
        Instantiate new delay extension component, connecting a new edge from
        the source vertex to it and new edges from it to the target (given
        by numBlocks).
        The outgoing edges cover each required block of delays, in groups of
        MAX_DELAYS_PER_NEURON delay slots (currently 16).
        """
        # If there are any connections with a delay of less than the maximum,
        # create a direct connection between the two populations only
        # containing these connections
        direct_synaptic_sublist = original_synapse_list.create_delay_sublist(
            0, max_delay_per_neuron)
        if direct_synaptic_sublist.get_max_n_connections() != 0:
            edge_to_merge = self._find_existing_edge(
                presynaptic_population._get_vertex,
                postsynaptic_population._get_vertex)
            if edge_to_merge is not None:
                self._projection_list_ranges = \
                    edge_to_merge.synapse_list.merge(direct_synaptic_sublist)
                self._projection_edge = edge_to_merge
            else:
                direct_edge = ProjectionPartitionableEdge(
                    presynaptic_population,
                    postsynaptic_population,
                    self._spinnaker.machine_time_step,
                    synapse_list=direct_synaptic_sublist,
                    label=label)
                self._spinnaker.add_edge(direct_edge)
                self._projection_edge = direct_edge
                self._projection_list_ranges = direct_synaptic_sublist.ranges()

        # Create a delay extension vertex to do the extra delays
        delay_vertex = presynaptic_population._internal_delay_vertex
        if delay_vertex is None:
            source_name = presynaptic_population._get_vertex.label
            delay_name = "{}_delayed".format(source_name)
            delay_vertex = DelayExtensionVertex(
                n_neurons=num_src_neurons,
                source_vertex=presynaptic_population._get_vertex,
                max_delay_per_neuron=max_delay_per_neuron,
                machine_time_step=machine_time_step,
                timescale_factor=timescale_factor,
                label=delay_name)
            presynaptic_population._internal_delay_vertex = delay_vertex
            presynaptic_population._get_vertex.add_constraint(
                PartitionerSameSizeAsVertexConstraint(delay_vertex))
            self._spinnaker.add_vertex(delay_vertex)

        # Create a connection from the source pynn_population.py to the
        # delay vertex
        existing_remaining_edge = self._find_existing_edge(
            presynaptic_population._get_vertex, delay_vertex)
        if existing_remaining_edge is None:
            new_label = "{}_to_DE".format(label)
            remaining_edge = DelayAfferentPartitionableEdge(
                presynaptic_population._get_vertex,
                delay_vertex,
                label=new_label)

            # add to graph
            self._spinnaker.add_edge(remaining_edge)

        # Create a list of the connections with delay larger than that which
        # can be handled by the neuron itself
        remaining_sublist = original_synapse_list.create_delay_sublist(
            max_delay_per_neuron + 1, max_delay_for_projection)

        # Create a special DelayEdge from the delay vertex to the outgoing
        # pynn_population.py, with the same set of connections
        delay_label = "DE to {}".format(label)
        num_blocks = int(
            math.floor(
                float(max_delay_for_projection - 1) /
                float(max_delay_per_neuron)))
        if num_blocks > delay_vertex.max_stages:
            delay_vertex.max_stages = num_blocks

        # Create the delay edge
        existing_delay_edge = self._find_existing_edge(
            delay_vertex, postsynaptic_population._get_vertex)
        if existing_delay_edge is not None:
            self._delay_list_ranges = existing_delay_edge.synapse_list.merge(
                remaining_sublist)
            self._delay_edge = existing_delay_edge
        else:
            self._delay_edge = DelayPartitionableEdge(
                presynaptic_population,
                postsynaptic_population,
                self._spinnaker.machine_time_step,
                num_blocks,
                max_delay_per_neuron,
                synapse_list=remaining_sublist,
                synapse_dynamics=synapse_dynamics,
                label=delay_label)
            self._delay_list_ranges = remaining_sublist.ranges()

            # add to graph
            self._spinnaker.add_edge(self._delay_edge)