def test_concat(self):
        """Test that passthrough node connection parameters can be combined
        with later passthrough node connection parameters to build a new set of
        parameters.
        """
        # Check that these parameters are combined correctly
        a = PassthroughNodeTransmissionParameters(
                Transform(size_in=5, size_out=3, transform=2.0,
                          slice_in=slice(2), slice_out=slice(2))
        )
        b = PassthroughNodeTransmissionParameters(
                Transform(size_in=3, size_out=3, slice_in=slice(2),
                          slice_out=slice(1, 3), transform=[-1.0, 1.5])
        )

        # Combine the connections
        c = a.concat(b)

        # Check the new parameters
        assert c.size_in == a.size_in
        assert c.size_out == b.size_out
        assert np.array_equal(c.slice_in, a.slice_in)
        assert np.array_equal(c.slice_out, b.slice_out)

        assert np.array_equal(
            c.full_transform(False, False),
            np.dot(b.full_transform(False, False),
                   a.full_transform(False, False))
        )
    def test_concat(self):
        """Test concatenating Node transmission parameters with passthrough
        node transmission parameters.
        """
        a = NodeTransmissionParameters(Transform(size_in=2,
                                                 size_out=5,
                                                 transform=[[2.0, 0.0],
                                                            [0.0, 2.0]],
                                                 slice_out=(1, 3)),
                                       pre_slice=slice(0, 3),
                                       function=object())
        b = PassthroughNodeTransmissionParameters(
            Transform(size_in=5,
                      size_out=2,
                      transform=[0.5, 0.25],
                      slice_in=(0, 3)))

        # Combine
        c = a.concat(b)
        assert c.size_in == a.size_in
        assert c.pre_slice == a.pre_slice
        assert c.function is a.function
        assert np.array_equal(
            c.full_transform(False, False),
            np.dot(b.full_transform(False, False),
                   a.full_transform(False, False)))
    def test_concat(self):
        """Test concatenating Node transmission parameters with passthrough
        node transmission parameters.
        """
        a = NodeTransmissionParameters(
            Transform(size_in=2, size_out=5,
                      transform=[[2.0, 0.0], [0.0, 2.0]],
                      slice_out=(1, 3)),
            pre_slice=slice(0, 3),
            function=object()
        )
        b = PassthroughNodeTransmissionParameters(
                Transform(size_in=5, size_out=2, transform=[0.5, 0.25],
                          slice_in=(0, 3))
        )

        # Combine
        c = a.concat(b)
        assert c.size_in == a.size_in
        assert c.pre_slice == a.pre_slice
        assert c.function is a.function
        assert np.array_equal(
            c.full_transform(False, False),
            np.dot(b.full_transform(False, False),
                   a.full_transform(False, False))
        )
    def test_concat_no_connection(self):
        """Test that None is returned if concatenating connections results in
        an empty transform.
        """
        a = PassthroughNodeTransmissionParameters(
                Transform(size_in=4, size_out=16, slice_out=slice(4),
                          transform=1.0)
        )
        b = PassthroughNodeTransmissionParameters(
                Transform(size_in=16, size_out=4, slice_in=slice(4, 8),
                          transform=1.0)
        )

        # Combine the connections
        assert a.concat(b) is None
Exemplo n.º 5
0
    def _copy_connections_from_interposer(self, node, port, conn, interposer,
                                          target_map):
        """Copy the pattern of connectivity from a node, replacing a specific
        connection with an interposer.
        """
        # Get the sinks of this connection
        sinks = self._connections[node][port][conn]

        # Extract parameters
        signal_pars, transmission_pars = conn

        # If the original object was an ensemble then modify the transmission
        # parameters to remove the decoders.
        if isinstance(node, EnsembleLIF):
            transmission_pars = PassthroughNodeTransmissionParameters(
                transmission_pars._transform)

        # Copy the connections to the sinks, note that we specify an empty
        # interposers dictionary so that no connections to further interposers
        # are inserted, likewise we specify no additional reception parameters.
        # The connectivity from the sink will be recursed if it is a
        # passthrough node.
        for sink in sinks:
            self._copy_connection(target_map, dict(), interposer,
                                  OutputPort.standard, signal_pars,
                                  transmission_pars, sink.sink_object,
                                  sink.port, sink.reception_parameters)
    def test_concat_no_connection(self):
        """Test that None is returned if concatenating connections results in
        an empty transform.
        """
        a = PassthroughNodeTransmissionParameters(
            Transform(size_in=4,
                      size_out=16,
                      slice_out=slice(4),
                      transform=1.0))
        b = PassthroughNodeTransmissionParameters(
            Transform(size_in=16,
                      size_out=4,
                      slice_in=slice(4, 8),
                      transform=1.0))

        # Combine the connections
        assert a.concat(b) is None
    def test_concat(self):
        """Test that passthrough node connection parameters can be combined
        with later passthrough node connection parameters to build a new set of
        parameters.
        """
        # Check that these parameters are combined correctly
        a = PassthroughNodeTransmissionParameters(
            Transform(size_in=5,
                      size_out=3,
                      transform=2.0,
                      slice_in=slice(2),
                      slice_out=slice(2)))
        b = PassthroughNodeTransmissionParameters(
            Transform(size_in=3,
                      size_out=3,
                      slice_in=slice(2),
                      slice_out=slice(1, 3),
                      transform=[-1.0, 1.5]))

        # Combine the connections
        c = a.concat(b)

        # Check the new parameters
        assert c.size_in == a.size_in
        assert c.size_out == b.size_out
        assert np.array_equal(c.slice_in, a.slice_in)
        assert np.array_equal(c.slice_out, b.slice_out)

        assert np.array_equal(
            c.full_transform(False, False),
            np.dot(b.full_transform(False, False),
                   a.full_transform(False, False)))
    def test_supports_global_inhibition(self):
        tp1 = PassthroughNodeTransmissionParameters(
            Transform(size_in=10, size_out=100, transform=np.ones((100, 10))))
        assert tp1.supports_global_inhibition

        tp2 = tp1.as_global_inhibition_connection
        assert tp2.size_in == tp1.size_in
        assert tp2.size_out == 1
        assert tp2.slice_out.size == 1
        assert np.array_equal(tp2.full_transform(), np.ones((1, 10)))
    def test_projects_to(self, method):
        """Test that the parameters correctly report if they transmit any
        values to the dimensions listed.
        """
        if method == "scalar":
            transform = 1.0
        elif method == "vector":
            transform = [1.0, 1.0, 1.0, 1.0]
        else:
            transform = np.eye(4)

        tp = PassthroughNodeTransmissionParameters(
                Transform(size_in=4, size_out=16, slice_out=slice(0, 4),
                          transform=transform)
        )

        assert tp.projects_to(slice(1))
        assert tp.projects_to(slice(5))
        assert not tp.projects_to(slice(4, 8))
        assert tp.projects_to((0, 1, 2, 4))
Exemplo n.º 10
0
    def test_insert_interposers_ignore_sinkless(self):
        """Test that interposers are inserted correctly, ignoring those that
        don't connect to anything.
        """
        cm = model.ConnectionMap()

        # Add a connection from a node to a passthrough node to the model
        nodes = [object(), object()]
        ptn = model.PassthroughNode()

        for node in nodes:
            cm.add_connection(
                node, OutputPort.standard, model.SignalParameters(weight=1),
                NodeTransmissionParameters(Transform(1, 1, 1)),
                ptn, InputPort.standard,
                model.ReceptionParameters(None, 1, None)
            )

        # Connect the passthrough node to another passthrough node
        ptn2 = model.PassthroughNode()
        cm.add_connection(ptn, OutputPort.standard, model.SignalParameters(),
                          PassthroughNodeTransmissionParameters(
                            Transform(1, 70, transform=np.ones((70, 1)))),
                          ptn2, InputPort.standard,
                          model.ReceptionParameters(None, 70, None))

        # Connect the passthrough node to another passthrough node
        ptn3 = model.PassthroughNode()
        cm.add_connection(ptn2, OutputPort.standard, model.SignalParameters(),
                          PassthroughNodeTransmissionParameters(
                            Transform(70, 70, 1)),
                          ptn3, InputPort.standard,
                          model.ReceptionParameters(None, 70, None))

        # Insert interposers, getting a list of interposers and a new
        # connection map.
        interposers, new_cm = cm.insert_interposers()
        assert len(interposers) == 0  # No interposers

        # No signals at all
        assert len(list(new_cm.get_signals())) == 0
    def test_projects_to(self, method):
        """Test that the parameters correctly report if they transmit any
        values to the dimensions listed.
        """
        if method == "scalar":
            transform = 1.0
        elif method == "vector":
            transform = [1.0, 1.0, 1.0, 1.0]
        else:
            transform = np.eye(4)

        tp = PassthroughNodeTransmissionParameters(
            Transform(size_in=4,
                      size_out=16,
                      slice_out=slice(0, 4),
                      transform=transform))

        assert tp.projects_to(slice(1))
        assert tp.projects_to(slice(5))
        assert not tp.projects_to(slice(4, 8))
        assert tp.projects_to((0, 1, 2, 4))
Exemplo n.º 12
0
    def test_insert_interposers_simple(self):
        """Test that interposers are inserted correctly."""
        cm = model.ConnectionMap()

        # Add a connection from a node to a passthrough node to the model
        nodes = [object(), object()]
        ptn = model.PassthroughNode()

        for node in nodes:
            cm.add_connection(
                node, OutputPort.standard, model.SignalParameters(weight=1),
                NodeTransmissionParameters(Transform(1, 1, 1)),
                ptn, InputPort.standard,
                model.ReceptionParameters(None, 1, None)
            )

        # Add a connection from the passthrough node to another node
        sink = object()
        sink_port = object()
        cm.add_connection(
            ptn, OutputPort.standard, model.SignalParameters(weight=70),
            PassthroughNodeTransmissionParameters(
                Transform(1, 70, np.ones((70, 1)))
            ),
            sink, sink_port, model.ReceptionParameters(None, 70, None)
        )

        # Insert interposers, getting a list of interposers and a new
        # connection map.
        interposers, new_cm = cm.insert_interposers()
        assert len(interposers) == 1  # Should insert 1 interposer
        interposer = interposers[0]

        # Check that each of the nodes connects to the interposer
        for node in nodes:
            from_node = new_cm._connections[node][OutputPort.standard]
            assert len(from_node) == 1

            for sinks in itervalues(from_node):
                assert len(sinks) == 1
                for s in sinks:
                    assert s.sink_object is interposer
                    assert s.port is InputPort.standard

        # Check that the interposer connects to the sink
        from_interposer = new_cm._connections[interposer][OutputPort.standard]
        assert len(from_interposer) == 1

        for sinks in itervalues(from_interposer):
            assert len(sinks) == 1
            for s in sinks:
                assert s.sink_object is sink
                assert s.port is sink_port
    def test_concat_no_connection(self):
        a = EnsembleTransmissionParameters(decoders=[[1.0, 2.0, 3.0, 4.0],
                                                     [4.0, 3.0, 2.0, 1.0]],
                                           transform=Transform(2,
                                                               4,
                                                               1,
                                                               slice_out=(1,
                                                                          2)))
        b = PassthroughNodeTransmissionParameters(
            Transform(size_in=4, size_out=2, transform=1.0, slice_in=(0, 3)))

        # Combine the parameters
        assert a.concat(b) is None
    def test_concat_no_connection(self):
        a = NodeTransmissionParameters(Transform(size_in=2,
                                                 size_out=5,
                                                 transform=[[2.0, 0.0],
                                                            [0.0, 2.0]],
                                                 slice_out=(1, 3)),
                                       pre_slice=slice(0, 3),
                                       function=object())
        b = PassthroughNodeTransmissionParameters(
            Transform(size_in=5,
                      size_out=2,
                      transform=[0.5, 0.25],
                      slice_in=(0, 2)))

        # Combine
        assert a.concat(b) is None
Exemplo n.º 15
0
    def test_insert_interposers_removes_passthrough_node(self):
        """Test that passthrough nodes are removed while inserting interposers.
        """
        cm = model.ConnectionMap()

        # Add a connection from a node to a passthrough node to the model
        node = object()
        ptn = model.PassthroughNode()
        cm.add_connection(
            node, OutputPort.standard, model.SignalParameters(weight=1),
            NodeTransmissionParameters(Transform(1, 1, 1)),
            ptn, InputPort.standard, model.ReceptionParameters(None, 1, None)
        )

        # Add a connection from the passthrough node to another node
        sink = object()
        cm.add_connection(
            ptn, OutputPort.standard, model.SignalParameters(weight=1),
            PassthroughNodeTransmissionParameters(Transform(1, 1, 1)),
            sink, InputPort.standard, model.ReceptionParameters(None, 1, None)
        )

        # Insert interposers, getting a list of interposers (empty) and a new
        # connection map.
        interposers, new_cm = cm.insert_interposers()
        assert len(interposers) == 0  # No interposers expected

        # Check that there is now just one connection from the node to the sink
        from_node = new_cm._connections[node]
        assert list(from_node) == [OutputPort.standard]

        for (signal_pars, transmission_pars), sinks in \
                iteritems(from_node[OutputPort.standard]):
            # Check the transmission parameters
            assert transmission_pars == NodeTransmissionParameters(
                Transform(1, 1, 1)
            )

            # Check that the sink is correct
            assert len(sinks) == 1
            for s in sinks:
                assert s.sink_object is sink
    def test_concat_no_learning_rule(self):
        a = EnsembleTransmissionParameters(decoders=[[1.0, 2.0, 3.0, 4.0],
                                                     [4.0, 3.0, 2.0, 1.0]],
                                           transform=Transform(2,
                                                               4,
                                                               1,
                                                               slice_out=(1,
                                                                          2)))
        b = PassthroughNodeTransmissionParameters(
            Transform(size_in=4, size_out=2, transform=1.0, slice_in=(1, 2)))

        # Combine the parameters
        c = a.concat(b)

        # Check the results
        assert isinstance(c, EnsembleTransmissionParameters)
        assert c.learning_rule is None
        assert c.size_out == b.size_out
        assert np.array_equal(c.slice_out, b.slice_out)
        assert np.array_equal(c.decoders, a.decoders)
Exemplo n.º 17
0
    def stack_interposers(self, interposers):
        """Return a new list of interposers and a new communication map
        resulting from combining compatible interposers.

        Returns
        -------
        ([Interposer, ...], ConnectionMap)
            A collection of new interposer operators and a new connection map
            with compatible interposers stacked.
        """
        # Determine which interposers can be stacked and build a map of
        # {interposer: (StackedInterposer, offset)}. Using this information we
        # copy signals from the old connection map into the new connection map,
        # replacing connections to stacked interposers by modifying their
        # output slice and stacking the connections from interposers in a
        # similar manner.

        # Create a mapping {{(sig params, sink), ...}: [Interposer, ...], ...}
        # to determine which interposers can be stacked (as they have a common
        # output set).
        compatible_interposers = defaultdict(list)
        for interposer in interposers:
            # Build up a set of the outputs for each interposer.
            outputs = list()
            for (sig_pars, _), sinks in iteritems(
                    self._connections[interposer][OutputPort.standard]):
                outputs.extend((sig_pars, sink) for sink in sinks)

            # Freeze the output set for hashing
            output_set = frozenset(outputs)
            compatible_interposers[output_set].append(interposer)

        # For each group of compatible interposers create a new, stacked,
        # interposer.
        stacked_interposers = dict()  # {StackedInterposer: [Interposer,...]}
        stacking = dict()  # {Interposers: (StackedInterposer, offset)}
        for interposer_group in itervalues(compatible_interposers):
            # Create the new interposer
            new_interposer = Filter(sum(i.size_in for i in interposer_group))
            stacked_interposers[new_interposer] = interposer_group

            # Store a mapping from the original interposers to the new
            # interposer and their offset into its input space.
            offset = 0
            for interposer in interposer_group:
                stacking[interposer] = (new_interposer, offset)
                offset += interposer.size_in  # Increase the offset

        # Create a new connection map and copy connections into it.
        cm = ConnectionMap()

        for source, ports_conns_sinks in iteritems(self._connections):
            # Ignore sources which are interposers for the moment
            if source in stacking:
                continue

            # Add connections to the new connection map, if they target an
            # interposer then modify the connection by projecting it into the
            # space of the new interposer.
            for port, conns_sinks in iteritems(ports_conns_sinks):
                for conn, sinks in iteritems(conns_sinks):
                    sps, tps = conn  # Extract parameters

                    for sink in sinks:
                        if sink.sink_object in stacking:
                            # If the sink is an interposer then add a modified
                            # connection to the new interposer.
                            sink_object, offset = stacking[sink.sink_object]

                            # Create a projection to apply.
                            slice_out = slice(offset, tps.size_out + offset)
                            projection = PassthroughNodeTransmissionParameters(
                                Transform(size_in=tps.size_out,
                                          size_out=sink_object.size_in,
                                          transform=1.0,
                                          slice_out=slice_out))

                            # Get the new transmission parameters
                            new_tps = tps.concat(projection)
                            assert new_tps is not None
                            cm.add_connection(source, port, copy(sps), new_tps,
                                              sink_object, sink.port,
                                              sink.reception_parameters)
                        else:
                            # Otherwise just add the signal unchanged
                            cm.add_connection(source, port, copy(sps), tps,
                                              sink.sink_object, sink.port,
                                              sink.reception_parameters)

        # For each stacked interposer build up a mapping from sinks, reception
        # parameters and signal parameters to the transmission parameters that
        # target it for each unstacked interposer. Subsequently stack these
        # transmission parameters and add the resulting signal to the network.
        for new_interposer, components in iteritems(stacked_interposers):
            # Map from (sink, signal_parameters) to an ordered list of
            # transmission parameters.
            connections = defaultdict(list)

            for node in components:
                for conns_and_sinks in itervalues(self._connections[node]):
                    for (sps, tps), sinks in iteritems(conns_and_sinks):
                        for sink in sinks:
                            connections[(sink, sps)].append(tps)

            # For each unique pair of sink and signal parameters add a new
            # connection to the network which is the result of stacking
            # together the transmission parameters.
            for (sink, sig_params), trans_pars in iteritems(connections):
                # Construct the combined signal parameters
                transmission_params = trans_pars[0].hstack(*trans_pars[1:])

                # Add the new connection to the network
                cm.add_connection(new_interposer, OutputPort.standard,
                                  copy(sig_params), transmission_params,
                                  sink.sink_object, sink.port,
                                  sink.reception_parameters)

        return list(stacked_interposers.keys()), cm
Exemplo n.º 18
0
    def test_insert_interposers_earliest_interposer_only(self):
        """Test that only the first interposer in a network of possible
        interposers is inserted.
        """
        cm = model.ConnectionMap()

        node = object()
        ptn1 = model.PassthroughNode()
        ptn2 = model.PassthroughNode()
        sink = object()

        # Add connections
        cm.add_connection(
            node, OutputPort.standard, model.SignalParameters(),
            NodeTransmissionParameters(Transform(16, 512, 1,
                                                 slice_out=slice(16, 32))),
            ptn1, InputPort.standard,
            model.ReceptionParameters(None, 512, None)
        )
        cm.add_connection(
            ptn1, OutputPort.standard, model.SignalParameters(),
            PassthroughNodeTransmissionParameters(
                Transform(512, 512, np.ones((512, 512)))
            ),
            ptn2, InputPort.standard,
            model.ReceptionParameters(None, 512, None)
        )
        cm.add_connection(
            ptn2, OutputPort.standard, model.SignalParameters(),
            PassthroughNodeTransmissionParameters(
                Transform(512, 1024, np.ones((1024, 512)))
            ),
            sink, InputPort.standard,
            model.ReceptionParameters(None, 1024, None)
        )

        # Insert interposers, only one should be included
        interposers, new_cm = cm.insert_interposers()
        assert len(interposers) == 1
        interposer = interposers[0]

        # Check that the node connects to the interposer and that the
        # interposer was the first passthrough node.
        from_node = new_cm._connections[node][OutputPort.standard]
        for (_, transmission_pars), sinks in iteritems(from_node):
            assert transmission_pars == NodeTransmissionParameters(
                Transform(16, 512, 1, slice_out=slice(16, 32))
            )

            assert len(sinks) == 1
            for s in sinks:
                assert s.sink_object is interposer

        # Check that the interposer connects to the sink
        from_interposer = new_cm._connections[interposer][OutputPort.standard]
        for (_, transmission_pars), sinks in iteritems(from_interposer):
            assert transmission_pars.size_in == 512
            assert transmission_pars.size_out == 1024

            assert len(sinks) == 1
            for s in sinks:
                assert s.sink_object is sink