Пример #1
0
def test_csa_one_to_one_connector():
    unittest_setup()
    connector = CSAConnector(csa.oneToOne)
    weight = 1.0
    delay = 2.0
    synapse_info = SynapseInformation(connector=None,
                                      pre_population=MockPopulation(10, "Pre"),
                                      post_population=MockPopulation(
                                          10, "Post"),
                                      prepop_is_view=False,
                                      postpop_is_view=False,
                                      rng=None,
                                      synapse_dynamics=None,
                                      synapse_type=None,
                                      receptor_type=None,
                                      is_virtual_machine=False,
                                      synapse_type_from_dynamics=False,
                                      weights=weight,
                                      delays=delay)
    connector.set_projection_information(synapse_info)
    pre_vertex_slice = Slice(0, 10)
    post_vertex_slice = Slice(0, 10)
    block = connector.create_synaptic_block([pre_vertex_slice],
                                            [post_vertex_slice],
                                            pre_vertex_slice,
                                            post_vertex_slice, 0, synapse_info)
    assert (len(block) > 0)
    assert (all(item["source"] == item["target"] for item in block))
    assert (all(item["weight"] == 1.0 for item in block))
    assert (all(item["delay"] == 2.0 for item in block))
Пример #2
0
def test_csa_from_list_connector():
    unittest_setup()
    conn_list = [(i, i + 1 % 10) for i in range(10)]
    connector = CSAConnector(conn_list)
    weight = 1.0
    delay = 2.0
    mock_synapse_info = SynapseInformation(
        connector=None,
        pre_population=MockPopulation(10, "Pre"),
        post_population=MockPopulation(10, "Post"),
        prepop_is_view=False,
        postpop_is_view=False,
        rng=None,
        synapse_dynamics=None,
        synapse_type=None,
        is_virtual_machine=False,
        weights=weight,
        delays=delay)
    connector.set_projection_information(mock_synapse_info)
    pre_vertex_slice = Slice(0, 10)
    post_vertex_slice = Slice(0, 10)
    block = connector.create_synaptic_block([pre_vertex_slice],
                                            [post_vertex_slice],
                                            pre_vertex_slice,
                                            post_vertex_slice, 0,
                                            mock_synapse_info)
    assert (len(block) > 0)
    assert (all(item["source"] == conn[0]
                for item, conn in zip(block, conn_list)))
    assert (all(item["target"] == conn[1]
                for item, conn in zip(block, conn_list)))
    assert (all(item["weight"] == 1.0 for item in block))
    assert (all(item["delay"] == 2.0 for item in block))
Пример #3
0
def test_csa_random_connector():
    unittest_setup()
    connector = CSAConnector(csa.random(0.05))
    weight = 1.0
    delay = 2.0
    mock_synapse_info = SynapseInformation(
        connector=None,
        pre_population=MockPopulation(10, "Pre"),
        post_population=MockPopulation(10, "Post"),
        prepop_is_view=False,
        postpop_is_view=False,
        rng=None,
        synapse_dynamics=None,
        synapse_type=None,
        is_virtual_machine=False,
        weights=weight,
        delays=delay)
    connector.set_projection_information(mock_synapse_info)
    pre_vertex_slice = Slice(0, 10)
    post_vertex_slice = Slice(0, 10)
    block = connector.create_synaptic_block([pre_vertex_slice],
                                            [post_vertex_slice],
                                            pre_vertex_slice,
                                            post_vertex_slice, 0,
                                            mock_synapse_info)
    assert (len(block) >= 0)
    assert (all(item["weight"] == 1.0 for item in block))
    assert (all(item["delay"] == 2.0 for item in block))
Пример #4
0
def test_connector_split():
    unittest_setup()
    n_sources = 1000
    n_targets = 1000
    n_connections = 10000
    pre_neurons_per_core = 57
    post_neurons_per_core = 59
    sources = numpy.random.randint(0, n_sources, n_connections)
    targets = numpy.random.randint(0, n_targets, n_connections)
    pre_slices = [
        Slice(i, i + pre_neurons_per_core - 1)
        for i in range(0, n_sources, pre_neurons_per_core)
    ]
    post_slices = [
        Slice(i, i + post_neurons_per_core - 1)
        for i in range(0, n_targets, post_neurons_per_core)
    ]

    connection_list = numpy.dstack((sources, targets))[0]
    connector = MockFromListConnector(connection_list)
    weight = 1.0
    delay = 1.0
    synapse_info = SynapseInformation(
        connector=None,
        pre_population=MockPopulation(n_sources, "Pre"),
        post_population=MockPopulation(n_targets, "Post"),
        prepop_is_view=False,
        postpop_is_view=False,
        rng=None,
        synapse_dynamics=None,
        synapse_type=None,
        is_virtual_machine=False,
        weights=weight,
        delays=delay)
    has_block = set()
    try:
        # Check each connection is in the right place
        for pre_slice in pre_slices:
            for post_slice in post_slices:
                block = connector.create_synaptic_block(
                    pre_slices, post_slices, pre_slice, post_slice, 1,
                    synapse_info)
                for source in block["source"]:
                    assert (pre_slice.lo_atom <= source <= pre_slice.hi_atom)
                for target in block["target"]:
                    assert (post_slice.lo_atom <= target <= post_slice.hi_atom)
                for item in block:
                    has_block.add((item["source"], item["target"]))

        # Check each connection has a place
        for source, target in zip(sources, targets):
            assert (source, target) in has_block

        # Check the split only happens once
        assert connector._split_count == 1
    except AssertionError as e:
        print(connection_list)
        raise e
Пример #5
0
def test_connector(clist, column_names, weights, delays, expected_clist,
                   expected_weights, expected_delays,
                   expected_extra_parameters, expected_extra_parameter_names):
    spynnaker8.setup()
    temp = tempfile.NamedTemporaryFile(delete=False)
    with temp as f:
        header = ''
        if column_names is not None:
            columns = ["i", "j"]
            columns.extend(column_names)
            header = 'columns = {}'.format(columns)
        if clist is not None and len(clist):
            numpy.savetxt(f, clist, header=header)
        elif len(header):
            f.write("# {}\n".format(header))

    connector = FromFileConnector(temp.name)
    if expected_clist is not None:
        assert (numpy.array_equal(connector.conn_list, expected_clist))
    else:
        assert (numpy.array_equal(connector.conn_list, clist))

    # Check extra parameters are as expected
    extra_params = connector.get_extra_parameters()
    extra_param_names = connector.get_extra_parameter_names()
    assert (numpy.array_equal(extra_params, expected_extra_parameters))
    assert (numpy.array_equal(extra_param_names,
                              expected_extra_parameter_names))
    if extra_params is not None:
        assert (len(extra_params.shape) == 2)
        assert (extra_params.shape[1] == len(extra_param_names))
        for i in range(len(extra_param_names)):
            assert (extra_params[:, i].shape == (len(clist), ))

    # Check weights and delays are used or ignored as expected
    pre_slice = Slice(0, 10)
    post_slice = Slice(0, 10)
    synapse_info = SynapseInformation(connector=None,
                                      pre_population=MockPopulation(10, "Pre"),
                                      post_population=MockPopulation(
                                          10, "Post"),
                                      prepop_is_view=False,
                                      postpop_is_view=False,
                                      rng=None,
                                      synapse_dynamics=None,
                                      synapse_type=None,
                                      receptor_type=None,
                                      is_virtual_machine=False,
                                      synapse_type_from_dynamics=False,
                                      weights=weights,
                                      delays=delays)
    block = connector.create_synaptic_block([pre_slice], [post_slice],
                                            pre_slice, post_slice, 1,
                                            synapse_info)
    assert (numpy.array_equal(block["weight"], numpy.array(expected_weights)))
    assert (numpy.array_equal(block["delay"], numpy.array(expected_delays)))
Пример #6
0
def test_get_max_row_length(dynamics, size, exception, max_size):
    io = SynapseIORowBased()
    population_table = MasterPopTableAsBinarySearch()
    synapse_information = SynapseInformation(None, dynamics, 0)
    in_edge = ProjectionApplicationEdge(None, None, synapse_information)
    if exception is not None:
        with pytest.raises(exception) as exc_info:
            io._get_max_row_length(size, dynamics, population_table, in_edge,
                                   size)
        assert exc_info.value.max_size == max_size
    else:
        actual_size = io._get_max_row_length(size, dynamics, population_table,
                                             in_edge, size)
        assert actual_size == max_size
Пример #7
0
def test_get_allowed_row_length(dynamics_class, timing, weight, size,
                                exception, max_size):
    spynnaker8.setup()
    if timing is not None and weight is not None:
        dynamics = dynamics_class(timing(), weight())
    else:
        dynamics = dynamics_class()
    synapse_information = SynapseInformation(None, None, None, False, False,
                                             None, None, dynamics, 0, True)
    in_edge = ProjectionApplicationEdge(None, None, synapse_information)
    if exception is not None:
        with pytest.raises(exception) as exc_info:
            _get_allowed_row_length(size, dynamics, in_edge, size)
        assert exc_info.value.max_size == max_size
    else:
        actual_size = _get_allowed_row_length(size, dynamics, in_edge, size)
        assert actual_size == max_size
Пример #8
0
def test_connector(clist, column_names, weights, delays, expected_clist,
                   expected_weights, expected_delays,
                   expected_extra_parameters, expected_extra_parameter_names):
    unittest_setup()
    connector = FromListConnector(clist, column_names=column_names)
    if expected_clist is not None:
        assert (numpy.array_equal(connector.conn_list, expected_clist))
    else:
        assert (numpy.array_equal(connector.conn_list, clist))

    # Check extra parameters are as expected
    extra_params = connector.get_extra_parameters()
    extra_param_names = connector.get_extra_parameter_names()
    assert (numpy.array_equal(extra_params, expected_extra_parameters))
    assert (numpy.array_equal(extra_param_names,
                              expected_extra_parameter_names))
    if extra_params is not None:
        assert (len(extra_params.shape) == 2)
        assert (extra_params.shape[1] == len(extra_param_names))
        for i in range(len(extra_param_names)):
            assert (extra_params[:, i].shape == (len(clist), ))

    # Check weights and delays are used or ignored as expected
    pre_slice = Slice(0, 10)
    post_slice = Slice(0, 10)
    synapse_info = SynapseInformation(connector=None,
                                      pre_population=MockPopulation(10, "Pre"),
                                      post_population=MockPopulation(
                                          10, "Post"),
                                      prepop_is_view=False,
                                      postpop_is_view=False,
                                      rng=None,
                                      synapse_dynamics=None,
                                      synapse_type=None,
                                      is_virtual_machine=False,
                                      weights=weights,
                                      delays=delays)
    block = connector.create_synaptic_block([pre_slice], [post_slice],
                                            pre_slice, post_slice, 1,
                                            synapse_info)
    assert (numpy.array_equal(block["weight"], numpy.array(expected_weights)))
    assert (numpy.array_equal(block["delay"], numpy.array(expected_delays)))
def test_slices():
    unittest_setup()
    s_info = SynapseInformation(None, None, None, False, False, None, None,
                                None, None, False, False, None, None)
    app_edge = ProjectionApplicationEdge(None, None, s_info)
    mv0_2 = SimpleMachineVertex(None, None, None, None, Slice(0, 1))
    mv2_4 = SimpleMachineVertex(None, None, None, None, Slice(2, 3))
    mv4_6 = SimpleMachineVertex(None, None, None, None, Slice(4, 5))
    app_edge.remember_associated_machine_edge(MachineEdge(mv0_2, mv2_4))
    app_edge.remember_associated_machine_edge(MachineEdge(mv4_6, mv0_2))
    app_edge.remember_associated_machine_edge(MachineEdge(mv0_2, mv2_4))
    assert app_edge.pre_slices == [Slice(0, 1), Slice(4, 5)]
    post1 = app_edge.post_slices
    assert post1 == [Slice(0, 1), Slice(2, 3)]
    app_edge.remember_associated_machine_edge(MachineEdge(mv0_2, mv0_2))
    app_edge.remember_associated_machine_edge(MachineEdge(mv2_4, mv2_4))
    assert app_edge.pre_slices == [Slice(0, 1), Slice(2, 3), Slice(4, 5)]
    post2 = app_edge.post_slices
    assert post1 == post2
    assert id(post1) != id(post2)
Пример #10
0
def test_csa_block_connector():
    unittest_setup()
    try:
        # This creates a block of size (2, 5) with a probability of 0.5; then
        # within the block an individual connection has a probability of 0.3
        connector = CSAConnector(
            csa.block(2, 5) * csa.random(0.5) * csa.random(0.3))
        weight = 1.0
        delay = 2.0
        mock_synapse_info = SynapseInformation(
            connector=None,
            pre_population=MockPopulation(10, "Pre"),
            post_population=MockPopulation(10, "Post"),
            prepop_is_view=False,
            postpop_is_view=False,
            rng=None,
            synapse_dynamics=None,
            synapse_type=None,
            receptor_type=None,
            is_virtual_machine=False,
            synapse_type_from_dynamics=False,
            weights=weight,
            delays=delay)

        connector.set_projection_information(mock_synapse_info)
        pre_vertex_slice = Slice(0, 10)
        post_vertex_slice = Slice(0, 10)
        block = connector.create_synaptic_block([pre_vertex_slice], 0,
                                                [post_vertex_slice], 0,
                                                pre_vertex_slice,
                                                post_vertex_slice, 0,
                                                mock_synapse_info)
        assert (len(block) >= 0)
        assert (all(item["weight"] == 1.0 for item in block))
        assert (all(item["delay"] == 2.0 for item in block))
    except TypeError as e:
        raise SkipTest("https://github.com/INCF/csa/issues/17") from e
    except RuntimeError as e:
        if sys.version_info >= (3, 7):
            raise SkipTest("https://github.com/INCF/csa/issues/16") from e
        raise e
Пример #11
0
def test_get_max_row_length(dynamics_class, timing, weight, size, exception,
                            max_size):
    MockSimulator.setup()
    if timing is not None and weight is not None:
        dynamics = dynamics_class(timing(), weight())
    else:
        dynamics = dynamics_class()
    io = SynapseIORowBased()
    population_table = MasterPopTableAsBinarySearch()
    synapse_information = SynapseInformation(None, None, None, None, None,
                                             None, dynamics, 0)
    in_edge = ProjectionApplicationEdge(None, None, synapse_information)
    if exception is not None:
        with pytest.raises(exception) as exc_info:
            io._get_max_row_length(size, dynamics, population_table, in_edge,
                                   size)
        assert exc_info.value.max_size == max_size
    else:
        actual_size = io._get_max_row_length(size, dynamics, population_table,
                                             in_edge, size)
        assert actual_size == max_size
Пример #12
0
    def test_write_synaptic_matrix_and_master_population_table(self):
        MockSimulator.setup()

        default_config_paths = os.path.join(
            os.path.dirname(abstract_spinnaker_common.__file__),
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME)

        config = conf_loader.load_config(
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME, default_config_paths)
        config.set("Simulation", "one_to_one_connection_dtcm_max_bytes", 40)

        machine_time_step = 1000.0

        pre_app_vertex = SimpleApplicationVertex(10)
        pre_vertex = SimpleMachineVertex(resources=None)
        pre_vertex_slice = Slice(0, 9)
        post_app_vertex = SimpleApplicationVertex(10)
        post_vertex = SimpleMachineVertex(resources=None)
        post_vertex_slice = Slice(0, 9)
        post_slice_index = 0
        one_to_one_connector_1 = OneToOneConnector(None)
        one_to_one_connector_1.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        one_to_one_connector_1.set_weights_and_delays(1.5, 1.0)
        one_to_one_connector_2 = OneToOneConnector(None)
        one_to_one_connector_2.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        one_to_one_connector_2.set_weights_and_delays(2.5, 2.0)
        all_to_all_connector = AllToAllConnector(None)
        all_to_all_connector.set_projection_information(
            pre_app_vertex, post_app_vertex, None, machine_time_step)
        all_to_all_connector.set_weights_and_delays(4.5, 4.0)
        direct_synapse_information_1 = SynapseInformation(
            one_to_one_connector_1, SynapseDynamicsStatic(), 0)
        direct_synapse_information_2 = SynapseInformation(
            one_to_one_connector_2, SynapseDynamicsStatic(), 1)
        all_to_all_synapse_information = SynapseInformation(
            all_to_all_connector, SynapseDynamicsStatic(), 0)
        app_edge = ProjectionApplicationEdge(pre_app_vertex, post_app_vertex,
                                             direct_synapse_information_1)
        app_edge.add_synapse_information(direct_synapse_information_2)
        app_edge.add_synapse_information(all_to_all_synapse_information)
        machine_edge = ProjectionMachineEdge(app_edge.synapse_information,
                                             pre_vertex, post_vertex)
        partition_name = "TestPartition"

        graph = MachineGraph("Test")
        graph.add_vertex(pre_vertex)
        graph.add_vertex(post_vertex)
        graph.add_edge(machine_edge, partition_name)

        graph_mapper = GraphMapper()
        graph_mapper.add_vertex_mapping(pre_vertex, pre_vertex_slice,
                                        pre_app_vertex)
        graph_mapper.add_vertex_mapping(post_vertex, post_vertex_slice,
                                        post_app_vertex)
        graph_mapper.add_edge_mapping(machine_edge, app_edge)

        weight_scales = [4096.0, 4096.0]

        key = 0
        routing_info = RoutingInfo()
        routing_info.add_partition_info(
            PartitionRoutingInfo(
                [BaseKeyAndMask(key, 0xFFFFFFF0)],
                graph.get_outgoing_edge_partition_starting_at_vertex(
                    pre_vertex, partition_name)))

        temp_spec = tempfile.mktemp()
        spec_writer = FileDataWriter(temp_spec)
        spec = DataSpecificationGenerator(spec_writer, None)
        master_pop_sz = 1000
        master_pop_region = 0
        all_syn_block_sz = 2000
        synapse_region = 1
        spec.reserve_memory_region(master_pop_region, master_pop_sz)
        spec.reserve_memory_region(synapse_region, all_syn_block_sz)

        synapse_type = MockSynapseType()

        synaptic_manager = SynapticManager(synapse_type=synapse_type,
                                           ring_buffer_sigma=5.0,
                                           spikes_per_second=100.0,
                                           config=config)
        synaptic_manager._write_synaptic_matrix_and_master_population_table(
            spec, [post_vertex_slice], post_slice_index, post_vertex,
            post_vertex_slice, all_syn_block_sz, weight_scales,
            master_pop_region, synapse_region, routing_info, graph_mapper,
            graph, machine_time_step)
        spec.end_specification()
        spec_writer.close()

        spec_reader = FileDataReader(temp_spec)
        executor = DataSpecificationExecutor(spec_reader,
                                             master_pop_sz + all_syn_block_sz)
        executor.execute()

        master_pop_table = executor.get_region(0)
        synaptic_matrix = executor.get_region(1)

        all_data = bytearray()
        all_data.extend(
            master_pop_table.region_data[:master_pop_table.max_write_pointer])
        all_data.extend(
            synaptic_matrix.region_data[:synaptic_matrix.max_write_pointer])
        master_pop_table_address = 0
        synaptic_matrix_address = master_pop_table.max_write_pointer
        direct_synapses_address = struct.unpack_from(
            "<I", synaptic_matrix.region_data)[0]
        direct_synapses_address += synaptic_matrix_address + 8
        indirect_synapses_address = synaptic_matrix_address + 4
        placement = Placement(None, 0, 0, 1)
        transceiver = MockTransceiverRawData(all_data)

        # Get the master population table details
        items = synaptic_manager._poptable_type\
            .extract_synaptic_matrix_data_location(
                key, master_pop_table_address, transceiver,
                placement.x, placement.y)

        # The first entry should be direct, but the rest should be indirect;
        # the second is potentially direct, but has been restricted by the
        # restriction on the size of the direct matrix
        assert len(items) == 3

        # TODO: This has been changed because direct matrices are disabled!
        assert not items[0][2]
        assert not items[1][2]
        assert not items[2][2]

        data_1, row_len_1 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=0,
            using_extra_monitor_cores=False)
        connections_1 = synaptic_manager._synapse_io.read_synapses(
            direct_synapse_information_1, pre_vertex_slice, post_vertex_slice,
            row_len_1, 0, 2, weight_scales, data_1, None,
            app_edge.n_delay_stages, machine_time_step)

        # The first matrix is a 1-1 matrix, so row length is 1
        assert row_len_1 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_1) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 1.5 for conn in connections_1])
        assert all([conn["delay"] == 1.0 for conn in connections_1])

        data_2, row_len_2 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=1,
            using_extra_monitor_cores=False)
        connections_2 = synaptic_manager._synapse_io.read_synapses(
            direct_synapse_information_2, pre_vertex_slice, post_vertex_slice,
            row_len_2, 0, 2, weight_scales, data_2, None,
            app_edge.n_delay_stages, machine_time_step)

        # The second matrix is a 1-1 matrix, so row length is 1
        assert row_len_2 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_2) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 2.5 for conn in connections_2])
        assert all([conn["delay"] == 2.0 for conn in connections_2])

        data_3, row_len_3 = synaptic_manager._retrieve_synaptic_block(
            transceiver=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=2,
            using_extra_monitor_cores=False)
        connections_3 = synaptic_manager._synapse_io.read_synapses(
            all_to_all_synapse_information, pre_vertex_slice,
            post_vertex_slice, row_len_3, 0, 2, weight_scales, data_3, None,
            app_edge.n_delay_stages, machine_time_step)

        # The third matrix is an all-to-all matrix, so length is n_atoms
        assert row_len_3 == post_vertex_slice.n_atoms

        # Check that all the connections have the right weight and delay
        assert len(connections_3) == \
            post_vertex_slice.n_atoms * pre_vertex_slice.n_atoms
        assert all([conn["weight"] == 4.5 for conn in connections_3])
        assert all([conn["delay"] == 4.0 for conn in connections_3])
Пример #13
0
def test_connectors(n_pre, n_post, n_in_slice, create_connector, weight,
                    delay):
    unittest_setup()
    max_target = 0
    max_source = 0
    max_row_length = None
    max_col_length = None
    for seed in range(10):
        numpy.random.seed(random.randint(0, 1000))
        connector = create_connector()
        synapse_info = SynapseInformation(
            connector=None,
            pre_population=MockPopulation(n_pre, "Pre"),
            post_population=MockPopulation(n_post, "Post"),
            prepop_is_view=False,
            postpop_is_view=False,
            rng=None,
            synapse_dynamics=None,
            synapse_type=None,
            receptor_type=None,
            is_virtual_machine=False,
            synapse_type_from_dynamics=False,
            weights=weight,
            delays=delay)
        connector.set_projection_information(synapse_info=synapse_info)

        pre_slices = [
            Slice(i, i + n_in_slice - 1) for i in range(0, n_pre, n_in_slice)
        ]
        post_slices = [
            Slice(i, i + n_in_slice - 1) for i in range(0, n_post, n_in_slice)
        ]
        pre_slice_index = 0
        post_slice_index = 0
        pre_vertex_slice = pre_slices[pre_slice_index]
        post_vertex_slice = post_slices[post_slice_index]
        synapse_type = 0
        pre_slice = pre_slices[pre_slice_index]
        post_slice = post_slices[post_slice_index]
        pre_range = numpy.arange(pre_slice.lo_atom, pre_slice.hi_atom + 2)
        post_range = numpy.arange(post_slice.lo_atom, post_slice.hi_atom + 2)

        max_delay = connector.get_delay_maximum(synapse_info)
        max_weight = connector.get_weight_maximum(synapse_info)
        if max_row_length is None:
            max_row_length = connector.\
                get_n_connections_from_pre_vertex_maximum(
                    post_vertex_slice, synapse_info)
        else:
            assert (max_row_length ==
                    connector.get_n_connections_from_pre_vertex_maximum(
                        post_vertex_slice, synapse_info))
        if max_col_length is None:
            max_col_length = connector.\
                get_n_connections_to_post_vertex_maximum(synapse_info)
        else:
            assert (max_col_length == connector.
                    get_n_connections_to_post_vertex_maximum(synapse_info))
        synaptic_block = connector.create_synaptic_block(
            pre_slices, post_slices, pre_vertex_slice, post_vertex_slice,
            synapse_type, synapse_info)
        source_histogram = numpy.histogram(synaptic_block["source"],
                                           pre_range)[0]
        target_histogram = numpy.histogram(synaptic_block["target"],
                                           post_range)[0]
        matrix_max_weight = (max(synaptic_block["weight"])
                             if len(synaptic_block) > 0 else 0)
        matrix_max_delay = (max(synaptic_block["delay"])
                            if len(synaptic_block) > 0 else 0)

        max_source = max((max(source_histogram), max_source))
        max_target = max((max(target_histogram), max_target))

        if len(post_slices) > post_slice_index + 1:
            test_post_slice = post_slices[post_slice_index + 1]
            test_synaptic_block = connector.create_synaptic_block(
                pre_slices, post_slices, pre_vertex_slice, test_post_slice,
                synapse_type, synapse_info)
            if len(test_synaptic_block) > 0:
                assert not numpy.array_equal(test_synaptic_block,
                                             synaptic_block)
        if len(pre_slices) > pre_slice_index + 1:
            test_pre_slice = pre_slices[pre_slice_index + 1]
            test_synaptic_block = connector.create_synaptic_block(
                pre_slices, post_slices, test_pre_slice, post_vertex_slice,
                synapse_type, synapse_info)
            if len(test_synaptic_block) > 0:
                assert not numpy.array_equal(test_synaptic_block,
                                             synaptic_block)

        try:
            assert max(source_histogram) <= max_row_length
            assert max(target_histogram) <= max_col_length
            assert matrix_max_weight <= max_weight
            assert matrix_max_delay <= max_delay
        except Exception:
            print(connector, n_pre, n_post, n_in_slice)
            print(max_row_length, max(source_histogram), source_histogram)
            print(max_col_length, max(target_histogram), target_histogram)
            print(max_weight, matrix_max_weight, synaptic_block["weight"])
            print(max_delay, matrix_max_delay, synaptic_block["delay"])
    print(connector, n_pre, n_post, n_in_slice, max_row_length, max_source,
          max_col_length, max_target)
Пример #14
0
    def test_write_synaptic_matrix_and_master_population_table(self):
        MockSimulator.setup()
        # Add an sdram so max SDRAM is high enough
        SDRAM(10000)

        # UGLY but the mock transceiver NEED generate_on_machine to be False
        AbstractGenerateConnectorOnMachine.generate_on_machine = self.say_false
        default_config_paths = os.path.join(
            os.path.dirname(abstract_spinnaker_common.__file__),
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME)

        config = conf_loader.load_config(
            AbstractSpiNNakerCommon.CONFIG_FILE_NAME, default_config_paths)
        config.set("Simulation", "one_to_one_connection_dtcm_max_bytes", 40)

        machine_time_step = 1000.0

        pre_app_vertex = SimpleApplicationVertex(10)
        pre_vertex_slice = Slice(0, 9)
        pre_vertex = pre_app_vertex.create_machine_vertex(
            pre_vertex_slice, None)
        post_app_vertex = SimpleApplicationVertex(10)
        post_vertex_slice = Slice(0, 9)
        post_vertex = post_app_vertex.create_machine_vertex(
            post_vertex_slice, None)
        post_slice_index = 0

        one_to_one_connector_1 = OneToOneConnector(None)
        direct_synapse_information_1 = SynapseInformation(
            one_to_one_connector_1, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 0, 1.5, 1.0)
        one_to_one_connector_1.set_projection_information(
            machine_time_step, direct_synapse_information_1)
        one_to_one_connector_2 = OneToOneConnector(None)
        direct_synapse_information_2 = SynapseInformation(
            one_to_one_connector_2, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 1, 2.5, 2.0)
        one_to_one_connector_2.set_projection_information(
            machine_time_step, direct_synapse_information_2)
        all_to_all_connector = AllToAllConnector(None)
        all_to_all_synapse_information = SynapseInformation(
            all_to_all_connector, pre_app_vertex, post_app_vertex, False,
            False, None, SynapseDynamicsStatic(), 0, 4.5, 4.0)
        all_to_all_connector.set_projection_information(
            machine_time_step, all_to_all_synapse_information)

        app_edge = ProjectionApplicationEdge(pre_app_vertex, post_app_vertex,
                                             direct_synapse_information_1)
        app_edge.add_synapse_information(direct_synapse_information_2)
        app_edge.add_synapse_information(all_to_all_synapse_information)
        machine_edge = app_edge.create_machine_edge(pre_vertex,
                                                    post_vertex,
                                                    label=None)
        partition_name = "TestPartition"

        graph = MachineGraph("Test")
        graph.add_vertex(pre_vertex)
        graph.add_vertex(post_vertex)
        graph.add_edge(machine_edge, partition_name)

        weight_scales = [4096.0, 4096.0]

        key = 0
        routing_info = RoutingInfo()
        routing_info.add_partition_info(
            PartitionRoutingInfo(
                [BaseKeyAndMask(key, 0xFFFFFFF0)],
                graph.get_outgoing_edge_partition_starting_at_vertex(
                    pre_vertex, partition_name)))

        temp_spec = tempfile.mktemp()
        spec_writer = FileDataWriter(temp_spec)
        spec = DataSpecificationGenerator(spec_writer, None)
        master_pop_sz = 1000
        all_syn_block_sz = 2000
        master_pop_region = 0
        synapse_region = 1
        direct_region = 2
        spec.reserve_memory_region(master_pop_region, master_pop_sz)
        spec.reserve_memory_region(synapse_region, all_syn_block_sz)

        synaptic_manager = SynapticManager(n_synapse_types=2,
                                           ring_buffer_sigma=5.0,
                                           spikes_per_second=100.0,
                                           config=config)
        # Poke in our testing region IDs
        synaptic_manager._pop_table_region = master_pop_region
        synaptic_manager._synaptic_matrix_region = synapse_region
        synaptic_manager._direct_matrix_region = direct_region

        synaptic_manager._write_synaptic_matrix_and_master_population_table(
            spec, [post_vertex_slice], post_slice_index, post_vertex,
            post_vertex_slice, all_syn_block_sz, weight_scales, routing_info,
            graph, machine_time_step)
        spec.end_specification()
        spec_writer.close()

        spec_reader = FileDataReader(temp_spec)
        executor = DataSpecificationExecutor(spec_reader,
                                             master_pop_sz + all_syn_block_sz)
        executor.execute()

        master_pop_table = executor.get_region(0)
        synaptic_matrix = executor.get_region(1)
        direct_matrix = executor.get_region(2)

        all_data = bytearray()
        all_data.extend(
            master_pop_table.region_data[:master_pop_table.max_write_pointer])
        all_data.extend(
            synaptic_matrix.region_data[:synaptic_matrix.max_write_pointer])
        all_data.extend(
            direct_matrix.region_data[:direct_matrix.max_write_pointer])
        master_pop_table_address = 0
        synaptic_matrix_address = master_pop_table.max_write_pointer
        direct_synapses_address = (synaptic_matrix_address +
                                   synaptic_matrix.max_write_pointer)
        direct_synapses_address += 4
        indirect_synapses_address = synaptic_matrix_address
        placement = Placement(None, 0, 0, 1)
        transceiver = MockTransceiverRawData(all_data)

        # Get the master population table details
        items = synaptic_manager._extract_synaptic_matrix_data_location(
            key, master_pop_table_address, transceiver, placement)

        # The first entry should be direct, but the rest should be indirect;
        # the second is potentially direct, but has been restricted by the
        # restriction on the size of the direct matrix
        assert len(items) == 3
        assert items[0][2]
        assert not items[1][2]
        assert not items[2][2]

        data_1, row_len_1 = synaptic_manager._retrieve_synaptic_block(
            txrx=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=0,
            using_monitors=False)
        connections_1 = synaptic_manager._read_synapses(
            direct_synapse_information_1, pre_vertex_slice, post_vertex_slice,
            row_len_1, 0, weight_scales, data_1, None, machine_time_step)

        # The first matrix is a 1-1 matrix, so row length is 1
        assert row_len_1 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_1) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 1.5 for conn in connections_1])
        assert all([conn["delay"] == 1.0 for conn in connections_1])

        data_2, row_len_2 = synaptic_manager._retrieve_synaptic_block(
            txrx=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=1,
            using_monitors=False)
        connections_2 = synaptic_manager._read_synapses(
            direct_synapse_information_2, pre_vertex_slice, post_vertex_slice,
            row_len_2, 0, weight_scales, data_2, None, machine_time_step)

        # The second matrix is a 1-1 matrix, so row length is 1
        assert row_len_2 == 1

        # Check that all the connections have the right weight and delay
        assert len(connections_2) == post_vertex_slice.n_atoms
        assert all([conn["weight"] == 2.5 for conn in connections_2])
        assert all([conn["delay"] == 2.0 for conn in connections_2])

        data_3, row_len_3 = synaptic_manager._retrieve_synaptic_block(
            txrx=transceiver,
            placement=placement,
            master_pop_table_address=master_pop_table_address,
            indirect_synapses_address=indirect_synapses_address,
            direct_synapses_address=direct_synapses_address,
            key=key,
            n_rows=pre_vertex_slice.n_atoms,
            index=2,
            using_monitors=False)
        connections_3 = synaptic_manager._read_synapses(
            all_to_all_synapse_information, pre_vertex_slice,
            post_vertex_slice, row_len_3, 0, weight_scales, data_3, None,
            machine_time_step)

        # The third matrix is an all-to-all matrix, so length is n_atoms
        assert row_len_3 == post_vertex_slice.n_atoms

        # Check that all the connections have the right weight and delay
        assert len(connections_3) == \
            post_vertex_slice.n_atoms * pre_vertex_slice.n_atoms
        assert all([conn["weight"] == 4.5 for conn in connections_3])
        assert all([conn["delay"] == 4.0 for conn in connections_3])
Пример #15
0
class Projection(object):
    """
    A container for all the connections of a given type (same synapse type and
    plasticity mechanisms) between two populations, together with methods to
    set parameters of those connections, including of plasticity mechanisms.
    """
    # pylint: disable=redefined-builtin
    __slots__ = [
        "__has_retrieved_synaptic_list_from_machine",
        "__host_based_synapse_list", "__projection_edge", "__requires_mapping",
        "__synapse_information", "__virtual_connection_list", "__label"
    ]

    def __init__(self,
                 pre_synaptic_population,
                 post_synaptic_population,
                 connector,
                 synapse_type=None,
                 source=None,
                 receptor_type=None,
                 space=None,
                 label=None):
        """
        :param ~spynnaker.pyNN.models.populations.PopulationBase \
                pre_synaptic_population:
        :param ~spynnaker.pyNN.models.populations.PopulationBase \
                post_synaptic_population:
        :param AbstractConnector connector:
        :param AbstractSynapseDynamics synapse_type:
        :param None source: Unsupported; must be None
        :param str receptor_type:
        :param ~pyNN.space.Space space:
        :param str label:
        """
        # pylint: disable=too-many-arguments, too-many-locals
        if source is not None:
            raise NotImplementedError(
                "sPyNNaker {} does not yet support multi-compartmental "
                "cells.".format(__version__))

        sim = get_simulator()
        self.__projection_edge = None
        self.__host_based_synapse_list = None
        self.__has_retrieved_synaptic_list_from_machine = False
        self.__requires_mapping = True
        self.__label = label

        pre_is_view = self.__check_population(pre_synaptic_population,
                                              connector)
        post_is_view = self.__check_population(post_synaptic_population,
                                               connector)

        # set default label
        if label is None:
            # set the projection's label to a default (maybe non-unique!)
            self.__label = ("from pre {} to post {} with connector {}".format(
                pre_synaptic_population.label, post_synaptic_population.label,
                connector))
            # give an auto generated label for the underlying edge
            label = "projection edge {}".format(sim.none_labelled_edge_count)
            sim.increment_none_labelled_edge_count()

        # Handle default synapse type
        if synapse_type is None:
            synapse_dynamics = SynapseDynamicsStatic()
        else:
            synapse_dynamics = synapse_type

        # set the space function as required
        if space is None:
            space = PyNNSpace()
        connector.set_space(space)

        pre_vertex = pre_synaptic_population._vertex
        post_vertex = post_synaptic_population._vertex

        if not isinstance(post_vertex, AbstractAcceptsIncomingSynapses):
            raise ConfigurationException(
                "postsynaptic population is not designed to receive"
                " synaptic projections")

        # sort out synapse type
        synaptic_type = post_vertex.get_synapse_id_by_target(receptor_type)
        synapse_type_from_dynamics = False
        if synaptic_type is None:
            synaptic_type = synapse_dynamics.get_synapse_id_by_target(
                receptor_type)
            synapse_type_from_dynamics = True
        if synaptic_type is None:
            raise ConfigurationException(
                "Synapse target {} not found in {}".format(
                    receptor_type, post_synaptic_population.label))

        # as a from-list connector can have plastic parameters, grab those (
        # if any) and add them to the synapse dynamics object
        if isinstance(connector, FromListConnector):
            connector._apply_parameters_to_synapse_type(synaptic_type)

        # round the delays to multiples of full timesteps
        # (otherwise SDRAM estimation calculations can go wrong)
        if ((not isinstance(synapse_dynamics.delay, RandomDistribution))
                and (not isinstance(synapse_dynamics.delay, str))):
            synapse_dynamics.set_delay(
                numpy.rint(
                    numpy.array(synapse_dynamics.delay) *
                    machine_time_step_per_ms()) * machine_time_step_ms())

        # set the plasticity dynamics for the post pop (allows plastic stuff
        #  when needed)
        post_vertex.set_synapse_dynamics(synapse_dynamics)

        # get rng if needed
        rng = connector.rng if hasattr(connector, "rng") else None
        # Set and store synapse information for future processing
        self.__synapse_information = SynapseInformation(
            connector, pre_synaptic_population, post_synaptic_population,
            pre_is_view, post_is_view, rng, synapse_dynamics, synaptic_type,
            receptor_type, sim.use_virtual_board, synapse_type_from_dynamics,
            synapse_dynamics.weight, synapse_dynamics.delay)

        # Set projection information in connector
        connector.set_projection_information(self.__synapse_information)

        # Find out if there is an existing edge between the populations
        edge_to_merge = self._find_existing_edge(pre_vertex, post_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 and add it
            self.__projection_edge = ProjectionApplicationEdge(
                pre_vertex,
                post_vertex,
                self.__synapse_information,
                label=label)
            sim.add_application_edge(self.__projection_edge,
                                     SPIKE_PARTITION_ID)

        # add projection to the SpiNNaker control system
        sim.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 sim.use_virtual_board:
            self.__virtual_connection_list = list()
            connection_holder = ConnectionHolder(
                None, False, pre_vertex.n_atoms, post_vertex.n_atoms,
                self.__virtual_connection_list)

            self.__synapse_information.add_pre_run_connection_holder(
                connection_holder)

        # If the target is a population, add to the list of incoming
        # projections
        if isinstance(post_vertex, AbstractPopulationVertex):
            post_vertex.add_incoming_projection(self)

        # If the source is a poisson, add to the list of outgoing projections
        if isinstance(pre_vertex, SpikeSourcePoissonVertex):
            pre_vertex.add_outgoing_projection(self)

    @staticmethod
    def __check_population(param, connector):
        """
        :param ~spynnaker.pyNN.models.populations.PopulationBase param:
        :param AbstractConnector connector:
        :return: Whether the parameter is a view
        :rtype: bool
        """
        if isinstance(param, Population):
            # Projections definitely work from Populations
            return False
        if not isinstance(param, PopulationView):
            raise ConfigurationException(
                "Unexpected parameter type {}. Expected Population".format(
                    type(param)))
        if not isinstance(connector, AbstractConnectorSupportsViewsOnMachine):
            raise NotImplementedError(
                "Projections over views not currently supported with the {}".
                format(connector))
        # Check whether the array is contiguous or not
        inds = param._indexes
        if inds != tuple(range(inds[0], inds[-1] + 1)):
            raise NotImplementedError(
                "Projections over views only work on contiguous arrays, "
                "e.g. view = pop[n:m], not view = pop[n,m]")
        # Projection is compatible with PopulationView
        return True

    def get(
            self,
            attribute_names,
            format,  # @ReservedAssignment
            gather=True,
            with_address=True,
            multiple_synapses='last'):
        """ Get a parameter/attribute of the projection.

        .. note::
            SpiNNaker always gathers.

        :param attribute_names: list of attributes to gather
        :type attribute_names: str or iterable(str)
        :param str format: ``"list"`` or ``"array"``
        :param bool gather: gather over all nodes
        :param bool with_address:
            True if the source and target are to be included
        :param str multiple_synapses:
            What to do with the data if format="array" and if the multiple
            source-target pairs with the same values exist.  Currently only
            "last" is supported
        :return: values selected
        """
        # pylint: disable=too-many-arguments
        if not gather:
            logger.warning("sPyNNaker always gathers from every core.")
        if multiple_synapses != 'last':
            raise ConfigurationException(
                "sPyNNaker only recognises multiple_synapses == last")

        return self.__get_data(attribute_names,
                               format,
                               with_address,
                               notify=None)

    def save(
            self,
            attribute_names,
            file,
            format='list',  # @ReservedAssignment
            gather=True,
            with_address=True):
        """ Print synaptic attributes (weights, delays, etc.) to file. In the\
            array format, zeros are printed for non-existent connections.\
            Values will be expressed in the standard PyNN units (i.e., \
            millivolts, nanoamps, milliseconds, microsiemens, nanofarads, \
            event per second).

        .. note::
            SpiNNaker always gathers.

        :param attribute_names:
        :type attribute_names: str or list(str)
        :param file: filename or open handle (which will be closed)
        :type file: str or pyNN.recording.files.BaseFile
        :param str format:
        :param bool gather: Ignored
        :param bool with_address:
        """
        # pylint: disable=too-many-arguments
        if not gather:
            warn_once(
                logger, "sPyNNaker only supports gather=True. We will run "
                "as if gather was set to True.")
        if isinstance(attribute_names, str):
            attribute_names = [attribute_names]
        if attribute_names in (['all'], ['connections']):
            attribute_names = \
                self._projection_edge.post_vertex.synapse_dynamics.\
                get_parameter_names()
        metadata = {"columns": attribute_names}
        if with_address:
            metadata["columns"] = ["i", "j"] + list(metadata["columns"])
        self.__get_data(attribute_names,
                        format,
                        with_address,
                        notify=functools.partial(self.__save_callback, file,
                                                 metadata))

    def __get_data(
            self,
            attribute_names,
            format,  # @ReservedAssignment
            with_address,
            notify):
        """ Internal data getter to add notify option

        :param attribute_names: list of attributes to gather
        :type attribute_names: str or iterable(str)
        :param str format: ``"list"`` or ``"array"``
        :param bool with_address:
        :param callable(ConnectionHolder,None) notify:
        :return: values selected
        """
        # fix issue with 1 versus many
        if isinstance(attribute_names, str):
            attribute_names = [attribute_names]

        data_items = list()
        if format != "list":
            with_address = False
        if with_address:
            data_items.append("source")
            data_items.append("target")
            if "source" in attribute_names:
                logger.warning(
                    "Ignoring request to get source as with_address=True. ")
                attribute_names.remove("source")
            if "target" in attribute_names:
                logger.warning(
                    "Ignoring request to get target as with_address=True. ")
                attribute_names.remove("target")

        # Split out attributes in to standard versus synapse dynamics data
        fixed_values = list()
        for attribute in attribute_names:
            data_items.append(attribute)
            if attribute not in {"source", "target", "weight", "delay"}:
                value = self._synapse_information.synapse_dynamics.get_value(
                    attribute)
                fixed_values.append((attribute, value))

        # Return the connection data
        return self._get_synaptic_data(format == "list",
                                       data_items,
                                       fixed_values,
                                       notify=notify)

    @staticmethod
    def __save_callback(save_file, metadata, data):
        """
        :param save_file:
        :type save_file: str or pyNN.recording.files.BaseFile
        :param dict(str,object) metadata:
        :param data:
        :type data: ConnectionHolder or numpy.ndarray
        """
        # Convert structured array to normal numpy array
        if hasattr(data, "dtype") and hasattr(data.dtype, "names"):
            dtype = [(name, "<f8") for name in data.dtype.names]
            data = data.astype(dtype)
        data = numpy.nan_to_num(data)
        if isinstance(save_file, str):
            data_file = StandardTextFile(save_file, mode='wb')
        else:
            data_file = save_file
        try:
            data_file.write(data, metadata)
        finally:
            data_file.close()

    @property
    def pre(self):
        """ The pre-population or population view.

        :rtype: ~spynnaker.pyNN.models.populations.PopulationBase
        """
        return self._synapse_information.pre_population

    @property
    def post(self):
        """ The post-population or population view.

        :rtype: ~spynnaker.pyNN.models.populations.PopulationBase
        """
        return self._synapse_information.post_population

    @property
    def label(self):
        """
        :rtype: str
        """
        return self.__label

    def __repr__(self):
        return "projection {}".format(self.__label)

    # -----------------------------------------------------------------

    @property
    def requires_mapping(self):
        """ Whether this projection requires mapping.

        :rtype: bool
        """
        return self.__requires_mapping

    def mark_no_changes(self):
        """ Mark this projection as not having changes to be mapped.
        """
        self.__requires_mapping = False

    @property
    def _synapse_information(self):
        """
        :rtype: SynapseInformation
        """
        return self.__synapse_information

    @property
    def _projection_edge(self):
        """
        :rtype: ProjectionApplicationEdge
        """
        return self.__projection_edge

    def _find_existing_edge(self, pre_synaptic_vertex, post_synaptic_vertex):
        """ Searches though the graph's edges to locate any\
            edge which has the same post and pre vertex

        :param pre_synaptic_vertex: the source vertex of the multapse
        :type pre_synaptic_vertex:
            ~pacman.model.graphs.application.ApplicationVertex
        :param post_synaptic_vertex: The destination vertex of the multapse
        :type post_synaptic_vertex:
            ~pacman.model.graphs.application.ApplicationVertex
        :return: None or the edge going to these vertices.
        :rtype: ~.ApplicationEdge
        """
        # Find edges ending at the postsynaptic vertex
        graph_edges = get_simulator().original_application_graph.\
            get_edges_ending_at_vertex(post_synaptic_vertex)

        # Search the edges for any that start at the presynaptic vertex
        for edge in graph_edges:
            if edge.pre_vertex == pre_synaptic_vertex:
                return edge
        return None

    def _get_synaptic_data(self,
                           as_list,
                           data_to_get,
                           fixed_values=None,
                           notify=None):
        """
        :param bool as_list:
        :param list(int) data_to_get:
        :param list(tuple(str,int)) fixed_values:
        :param callable(ConnectionHolder,None) notify:
        :rtype: ConnectionHolder
        """
        # pylint: disable=too-many-arguments
        post_vertex = self.__projection_edge.post_vertex
        pre_vertex = self.__projection_edge.pre_vertex

        # If in virtual board mode, the connection data should be set
        if self.__virtual_connection_list is not None:
            connection_holder = ConnectionHolder(
                data_to_get,
                as_list,
                pre_vertex.n_atoms,
                post_vertex.n_atoms,
                self.__virtual_connection_list,
                fixed_values=fixed_values,
                notify=notify)
            connection_holder.finish()
            return connection_holder

        # if not virtual board, make connection holder to be filled in at
        # possible later date
        connection_holder = ConnectionHolder(data_to_get,
                                             as_list,
                                             pre_vertex.n_atoms,
                                             post_vertex.n_atoms,
                                             fixed_values=fixed_values,
                                             notify=notify)

        # If we haven't run, add the holder to get connections, and return it
        # and set up a callback for after run to fill in this connection holder
        if not get_simulator().has_ran:
            self.__synapse_information.add_pre_run_connection_holder(
                connection_holder)
            return connection_holder

        # Otherwise, get the connections now, as we have ran and therefore can
        # get them
        connections = post_vertex.get_connections_from_machine(
            get_simulator().transceiver,
            get_simulator().placements, self.__projection_edge,
            self.__synapse_information)
        if connections is not None:
            connection_holder.add_connections(connections)
            connection_holder.finish()
        return connection_holder

    def _clear_cache(self):
        post_vertex = self.__projection_edge.post_vertex
        if isinstance(post_vertex, AbstractAcceptsIncomingSynapses):
            post_vertex.clear_connection_cache()

    # -----------------------------------------------------------------

    def set(self, **attributes):  # @UnusedVariable
        # pylint: disable=unused-argument
        """
        .. warning::
            Not implemented.
        """
        _we_dont_do_this_now()

    def getWeights(
            self,
            format='list',  # @ReservedAssignment
            gather=True):
        """
        .. deprecated:: 5.0
            Use ``get('weight')`` instead.
        """
        logger.warning("getWeights is deprecated.  Use get('weight') instead")
        return self.get('weight', format, gather, with_address=False)

    def getDelays(
            self,
            format='list',  # @ReservedAssignment
            gather=True):
        """
        .. deprecated:: 5.0
            Use ``get('delay')`` instead.
        """
        logger.warning("getDelays is deprecated.  Use get('delay') instead")
        return self.get('delay', format, gather, with_address=False)

    def getSynapseDynamics(
            self,
            parameter_name,
            format='list',  # @ReservedAssignment
            gather=True):
        """
        .. deprecated:: 5.0
            Use ``get(parameter_name)`` instead.
        """
        logger.warning(
            "getSynapseDynamics is deprecated. Use get(parameter_name)"
            " instead")
        return self.get(parameter_name, format, gather, with_address=False)

    def saveConnections(
            self,
            file,  # @ReservedAssignment
            gather=True,
            compatible_output=True):
        """
        .. deprecated:: 5.0
            Use ``save('all')`` instead.
        """
        if not compatible_output:
            logger.warning("SpiNNaker only supports compatible_output=True.")
        logger.warning(
            "saveConnections is deprecated. Use save('all') instead")
        self.save('all', file, format='list', gather=gather)

    def printWeights(
            self,
            file,
            format='list',  # @ReservedAssignment
            gather=True):
        """
        .. deprecated:: 5.0
            Use ``save('weight')`` instead.
        """
        logger.warning(
            "printWeights is deprecated. Use save('weight') instead")
        self.save('weight', file, format, gather)

    def printDelays(
            self,
            file,
            format='list',  # @ReservedAssignment
            gather=True):
        """
        .. deprecated:: 5.0
            Use ``save('delay')`` instead.

        Print synaptic weights to file. In the array format, zeros are
        printed for non-existent connections.
        """
        logger.warning("printDelays is deprecated. Use save('delay') instead")
        self.save('delay', file, format, gather)

    def weightHistogram(
            self,
            min=None,
            max=None,  # @ReservedAssignment
            nbins=10):
        """
        .. deprecated:: 5.0
            Use ``numpy.histogram`` on the weights instead.

        Return a histogram of synaptic weights.
        If ``min`` and ``max`` are not given, the minimum and maximum weights
        are calculated automatically.
        """
        logger.warning(
            "weightHistogram is deprecated. Use numpy.histogram function"
            " instead")
        pynn_common.Projection.weightHistogram(self,
                                               min=min,
                                               max=max,
                                               nbins=nbins)

    def size(self, gather=True):  # @UnusedVariable
        # pylint: disable=unused-argument
        """ Return the total number of connections.

        .. note::
            SpiNNaker always gathers.
        .. warning::
            Not implemented.

        :param bool gather:
            If False, only get the number of connections locally.
        """
        # TODO
        _we_dont_do_this_now()
Пример #16
0
    def __init__(self, spinnaker_control, connector, synapse_dynamics_stdp,
                 target, pre_synaptic_population, post_synaptic_population,
                 rng, machine_time_step, user_max_delay, label,
                 time_scale_factor):
        # pylint: disable=too-many-arguments, too-many-locals
        self._spinnaker_control = spinnaker_control
        self._projection_edge = None
        self._host_based_synapse_list = None
        self._has_retrieved_synaptic_list_from_machine = False
        self._requires_mapping = True
        self._label = None

        if not isinstance(post_synaptic_population._get_vertex,
                          AbstractAcceptsIncomingSynapses):
            raise ConfigurationException(
                "postsynaptic population is not designed to receive"
                " synaptic projections")

        # sort out synapse type
        synapse_type = post_synaptic_population._get_vertex\
            .get_synapse_id_by_target(target)
        if synapse_type is None:
            raise ConfigurationException(
                "Synapse target {} not found in {}".format(
                    target, post_synaptic_population.label))

        # set the plasticity dynamics for the post pop (allows plastic stuff
        #  when needed)
        post_synaptic_population._get_vertex.set_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(pre_synaptic_population,
                                             post_synaptic_population, rng,
                                             machine_time_step)

        # handle max delay
        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
        post_vertex_max_supported_delay_ms = \
            post_synaptic_population._get_vertex \
            .get_maximum_delay_supported_in_ms(machine_time_step)
        if max_delay > (post_vertex_max_supported_delay_ms +
                        _delay_extension_max_supported_delay):
            raise ConfigurationException(
                "The maximum delay {} for projection is not supported".format(
                    max_delay))

        if max_delay > user_max_delay / (machine_time_step / 1000.0):
            logger.warning("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(
            pre_synaptic_population._get_vertex,
            post_synaptic_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 = ProjectionApplicationEdge(
                pre_synaptic_population._get_vertex,
                post_synaptic_population._get_vertex,
                self._synapse_information,
                label=label)

            # add edge to the graph
            spinnaker_control.add_application_edge(
                self._projection_edge, constants.SPIKE_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(
                pre_synaptic_population, post_synaptic_population, max_delay,
                post_vertex_max_supported_delay_ms, machine_time_step,
                time_scale_factor)
            self._projection_edge.delay_edge = delay_edge

        # add projection to the SpiNNaker control system
        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 = pre_synaptic_population._get_vertex
            post_vertex = post_synaptic_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)
Пример #17
0
    def __init__(self,
                 pre_synaptic_population,
                 post_synaptic_population,
                 connector,
                 synapse_type=None,
                 source=None,
                 receptor_type=None,
                 space=None,
                 label=None):
        """
        :param ~spynnaker.pyNN.models.populations.PopulationBase \
                pre_synaptic_population:
        :param ~spynnaker.pyNN.models.populations.PopulationBase \
                post_synaptic_population:
        :param AbstractConnector connector:
        :param AbstractSynapseDynamics synapse_type:
        :param None source: Unsupported; must be None
        :param str receptor_type:
        :param ~pyNN.space.Space space:
        :param str label:
        """
        # pylint: disable=too-many-arguments, too-many-locals
        if source is not None:
            raise NotImplementedError(
                "sPyNNaker {} does not yet support multi-compartmental "
                "cells.".format(__version__))

        sim = get_simulator()
        self.__projection_edge = None
        self.__host_based_synapse_list = None
        self.__has_retrieved_synaptic_list_from_machine = False
        self.__requires_mapping = True
        self.__label = label

        pre_is_view = self.__check_population(pre_synaptic_population,
                                              connector)
        post_is_view = self.__check_population(post_synaptic_population,
                                               connector)

        # set default label
        if label is None:
            # set the projection's label to a default (maybe non-unique!)
            self.__label = ("from pre {} to post {} with connector {}".format(
                pre_synaptic_population.label, post_synaptic_population.label,
                connector))
            # give an auto generated label for the underlying edge
            label = "projection edge {}".format(sim.none_labelled_edge_count)
            sim.increment_none_labelled_edge_count()

        # Handle default synapse type
        if synapse_type is None:
            synapse_dynamics = SynapseDynamicsStatic()
        else:
            synapse_dynamics = synapse_type

        # set the space function as required
        if space is None:
            space = PyNNSpace()
        connector.set_space(space)

        pre_vertex = pre_synaptic_population._vertex
        post_vertex = post_synaptic_population._vertex

        if not isinstance(post_vertex, AbstractAcceptsIncomingSynapses):
            raise ConfigurationException(
                "postsynaptic population is not designed to receive"
                " synaptic projections")

        # sort out synapse type
        synaptic_type = post_vertex.get_synapse_id_by_target(receptor_type)
        synapse_type_from_dynamics = False
        if synaptic_type is None:
            synaptic_type = synapse_dynamics.get_synapse_id_by_target(
                receptor_type)
            synapse_type_from_dynamics = True
        if synaptic_type is None:
            raise ConfigurationException(
                "Synapse target {} not found in {}".format(
                    receptor_type, post_synaptic_population.label))

        # as a from-list connector can have plastic parameters, grab those (
        # if any) and add them to the synapse dynamics object
        if isinstance(connector, FromListConnector):
            connector._apply_parameters_to_synapse_type(synaptic_type)

        # round the delays to multiples of full timesteps
        # (otherwise SDRAM estimation calculations can go wrong)
        if ((not isinstance(synapse_dynamics.delay, RandomDistribution))
                and (not isinstance(synapse_dynamics.delay, str))):
            synapse_dynamics.set_delay(
                numpy.rint(
                    numpy.array(synapse_dynamics.delay) *
                    machine_time_step_per_ms()) * machine_time_step_ms())

        # set the plasticity dynamics for the post pop (allows plastic stuff
        #  when needed)
        post_vertex.set_synapse_dynamics(synapse_dynamics)

        # get rng if needed
        rng = connector.rng if hasattr(connector, "rng") else None
        # Set and store synapse information for future processing
        self.__synapse_information = SynapseInformation(
            connector, pre_synaptic_population, post_synaptic_population,
            pre_is_view, post_is_view, rng, synapse_dynamics, synaptic_type,
            receptor_type, sim.use_virtual_board, synapse_type_from_dynamics,
            synapse_dynamics.weight, synapse_dynamics.delay)

        # Set projection information in connector
        connector.set_projection_information(self.__synapse_information)

        # Find out if there is an existing edge between the populations
        edge_to_merge = self._find_existing_edge(pre_vertex, post_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 and add it
            self.__projection_edge = ProjectionApplicationEdge(
                pre_vertex,
                post_vertex,
                self.__synapse_information,
                label=label)
            sim.add_application_edge(self.__projection_edge,
                                     SPIKE_PARTITION_ID)

        # add projection to the SpiNNaker control system
        sim.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 sim.use_virtual_board:
            self.__virtual_connection_list = list()
            connection_holder = ConnectionHolder(
                None, False, pre_vertex.n_atoms, post_vertex.n_atoms,
                self.__virtual_connection_list)

            self.__synapse_information.add_pre_run_connection_holder(
                connection_holder)

        # If the target is a population, add to the list of incoming
        # projections
        if isinstance(post_vertex, AbstractPopulationVertex):
            post_vertex.add_incoming_projection(self)

        # If the source is a poisson, add to the list of outgoing projections
        if isinstance(pre_vertex, SpikeSourcePoissonVertex):
            pre_vertex.add_outgoing_projection(self)