def test_node_to_gi(self, passthrough):
        # Create the ingoing connection parameters
        if not passthrough:
            in_transmission_params = NodeTransmissionParameters(
                slice(10, 20), mock.Mock(), np.ones((100, 1)))
        else:
            in_transmission_params = PassthroughNodeTransmissionParameters(
                np.ones((100, 1)))

        # Create the outgoing connection parameters
        out_transmission_params = PassthroughNodeTransmissionParameters(
            np.eye(100))

        # Combine the parameter sets
        new_tps, new_in_port = model_utils._combine_transmission_params(
            in_transmission_params, out_transmission_params,
            EnsembleInputPort.neurons)

        # Check that all the parameters are correct
        if not passthrough:
            assert new_tps.pre_slice == in_transmission_params.pre_slice
            assert new_tps.function is in_transmission_params.function

        assert np.all(
            new_tps.transform == np.dot(out_transmission_params.transform,
                                        in_transmission_params.transform)[0])
        assert new_tps.transform.shape[0] == 1
        assert new_in_port is EnsembleInputPort.global_inhibition
    def test_node_to_x(self, passthrough, final_port):
        # Create the ingoing connection parameters
        if not passthrough:
            in_transmission_params = NodeTransmissionParameters(
                slice(10, 15),
                mock.Mock(),
                np.random.uniform(size=(10, 5)),
            )
        else:
            in_transmission_params = PassthroughNodeTransmissionParameters(
                np.random.uniform(size=(10, 5)), )

        # Create the outgoing connection parameters
        out_transmission_params = PassthroughNodeTransmissionParameters(
            np.hstack((np.zeros((5, 5)), np.eye(5))))

        # Combine the parameter sets
        new_tps, new_in_port = model_utils._combine_transmission_params(
            in_transmission_params, out_transmission_params, final_port)

        # Check that all the parameters are correct
        if not passthrough:
            assert new_tps.pre_slice == in_transmission_params.pre_slice
            assert new_tps.function is in_transmission_params.function

        assert np.all(
            new_tps.transform == np.dot(out_transmission_params.transform,
                                        in_transmission_params.transform))
        assert new_tps.transform.shape == (5, 5)
        assert new_in_port is final_port
예제 #3
0
    def test_x_to_x_optimize_out(self, from_type, final_port):
        # Create the ingoing connection parameters
        in_transmission_params = {
            "ensemble": EnsembleTransmissionParameters(np.dot([[1.0], [0.0]], np.random.uniform(size=(100, 1)).T), None),
            "node": NodeTransmissionParameters(
                        slice(10, 20),
                        mock.Mock(),
                        np.array([[1.0], [0.0]])
                    ),
            "ptn": PassthroughNodeTransmissionParameters(
                       np.array([[1.0], [0.0]])
                   ),
        }[from_type]

        # Create the outgoing connection parameters
        out_transmission_params = PassthroughNodeTransmissionParameters(
            np.array([[0.0, 0.0], [0.0, 1.0]])
        )

        # Combine the parameter sets
        new_tps, new_in_port = model_utils._combine_transmission_params(
                in_transmission_params,
                out_transmission_params,
                final_port
            )

        # Check that the connection is optimised out
        assert new_tps is None
        assert new_in_port is None
예제 #4
0
    def test_transmits_signal(self):
        # Create a series of transmission parameters
        ptn_2_to_8 = np.zeros((32, 6))
        ptn_2_to_8[2:8, :] = np.eye(6)
        tp0 = PassthroughNodeTransmissionParameters(ptn_2_to_8.T)
        tp0_slice = set(range(2, 8))

        ptn_20_to_26 = np.zeros((32, 6))
        ptn_20_to_26[20:26, :] = np.eye(6)
        tp1 = PassthroughNodeTransmissionParameters(ptn_20_to_26.T)
        tp1_slice = set(range(20, 26))

        signal_parameter_slices = [(tp0, tp0_slice),
                                   (tp1, tp1_slice),
                                   ]

        # Create a series of vertex slices
        pfss = [
            ParallelFilterSlice(slice(None), slice(0, 16), {},
                                signal_parameter_slices),
            ParallelFilterSlice(slice(None), slice(8, 24), {},
                                signal_parameter_slices),
            ParallelFilterSlice(slice(None), slice(16, 32), {},
                                signal_parameter_slices),
        ]

        # Check that `transmits_signal` responds correctly
        assert pfss[0].transmits_signal(None, tp0)
        assert not pfss[1].transmits_signal(None, tp0)
        assert not pfss[2].transmits_signal(None, tp0)

        assert not pfss[0].transmits_signal(None, tp1)
        assert pfss[1].transmits_signal(None, tp1)
        assert pfss[2].transmits_signal(None, tp1)
예제 #5
0
def test_get_transforms_and_keys():
    """Test that the complete transform matrix is constructed correctly and
    that appropriate keys are assigned.
    """
    # Create 2 mock signals and associated connections
    sig_a_ks_0 = mock.Mock()
    sig_a_ks_1 = mock.Mock()
    sig_a_kss = {
        0: sig_a_ks_0,
        1: sig_a_ks_1,
    }

    sig_a_ks = mock.Mock()
    sig_a_ks.side_effect = lambda index: sig_a_kss[index]
    sig_a = SignalParameters(keyspace=sig_a_ks)

    conn_a = PassthroughNodeTransmissionParameters(np.eye(2))

    sig_b_ks_0 = mock.Mock()
    sig_b_kss = {
        0: sig_b_ks_0,
    }

    sig_b_ks = mock.Mock()
    sig_b_ks.side_effect = lambda index: sig_b_kss[index]
    sig_b = SignalParameters(keyspace=sig_b_ks)

    conn_b = PassthroughNodeTransmissionParameters(np.array([[0.5, 0.5]]))
    transform_b = conn_b.transform

    # Create the dictionary type that will be used
    pars = [(sig_a, conn_a), (sig_b, conn_b)]

    # Get the transforms and keys
    transforms, keys, signal_parameter_slices = get_transforms_and_keys(pars)

    # Check that the transforms and keys are correct
    assert set(keys) == set([sig_a_ks_0, sig_a_ks_1, sig_b_ks_0])
    assert transforms.shape == (len(keys), 2)
    assert (np.all(transforms[0] == transform_b) or
            np.all(transforms[2] == transform_b))

    # Check that the signal parameter slices are correct
    for (par, sl) in signal_parameter_slices:
        if par == conn_a:
            assert sl == set(range(0, 2)) or sl == set(range(1, 3))
        else:
            assert par == conn_b
            assert sl == set(range(0, 1)) or sl == set(range(2, 3))
예제 #6
0
    def test_accepts_signal(self):
        # Create a series of vertex slices
        pfss = [
            ParallelFilterSlice(slice(0, 16), slice(None)),
            ParallelFilterSlice(slice(8, 24), slice(None)),
            ParallelFilterSlice(slice(16, 32), slice(None)),
        ]

        # Create a series of transmission parameters, of current known types.
        ens_0_to_8 = np.random.uniform(size=(100, 10))
        ens_0_to_8[:, 8:] = 0.0
        tp0 = EnsembleTransmissionParameters(ens_0_to_8, 1.0)

        ptn_20_to_26 = np.zeros((32, 6))
        ptn_20_to_26[20:26, :] = np.eye(6)
        tp1 = PassthroughNodeTransmissionParameters(ptn_20_to_26)

        # Check that `accepts_signal` responds correctly
        assert pfss[0].accepts_signal(None, tp0)
        assert not pfss[1].accepts_signal(None, tp0)
        assert not pfss[2].accepts_signal(None, tp0)

        assert not pfss[0].accepts_signal(None, tp1)
        assert pfss[1].accepts_signal(None, tp1)
        assert pfss[2].accepts_signal(None, tp1)
예제 #7
0
def test_get_transforms_and_keys_removes_zeroed_rows(latching):
    """Check that zeroed rows (those that would always result in zero valued
    packets) are removed, and the keys miss this value as well.
    """
    transform = np.ones((10, 5))
    transform[1, :] = 0.0
    transform[4:7, :] = 0.0
    transform[:, 1] = 0.0

    # Create a signal and keyspace
    sig = SignalParameters(latching=latching)

    # Create a mock connection
    conn = PassthroughNodeTransmissionParameters(
        Transform(size_in=5, size_out=10, transform=transform))

    signals_connections = [(sig, conn)]

    # Get the transform and keys
    t, keys, _ = get_transforms_and_keys(signals_connections, slice(0, 5))

    if not latching:
        # Check the transform is correct
        assert np.all(t == np.vstack((transform[0], transform[2:4],
                                      transform[7:])))

        # Check the keys were called for correctly
        assert keys == [(sig, {"index": i}) for i in [0, 2, 3, 7, 8, 9]]
    else:
        # Check the transform is correct
        assert np.all(t == t)

        # Check the keys were called for correctly
        assert keys == [(sig, {"index": i}) for i in range(10)]
예제 #8
0
def test_get_transforms_and_keys():
    """Test that the complete transform matrix is constructed correctly and
    that appropriate keys are assigned.
    """
    # Create 2 mock signals and associated connections
    sig_a = SignalParameters()
    conn_a = PassthroughNodeTransmissionParameters(
        Transform(size_in=2, size_out=2, transform=np.eye(2)))

    sig_b = SignalParameters()
    conn_b = PassthroughNodeTransmissionParameters(
        Transform(size_in=2, size_out=1, transform=np.array([[0.5, 0.5]])))
    transform_b = conn_b.transform

    # Create the dictionary type that will be used
    pars = [(sig_a, conn_a), (sig_b, conn_b)]

    # Get the transforms and keys
    transforms, keys, signal_parameter_slices = \
        get_transforms_and_keys(pars, slice(0, 2))

    # Check that the transforms and keys are correct
    assert (keys == [(sig_b, {
        "index": 0
    }), (sig_a, {
        "index": 0
    }), (sig_a, {
        "index": 1
    })] or keys == [(sig_a, {
        "index": 0
    }), (sig_a, {
        "index": 1
    }), (sig_b, {
        "index": 0
    })])
    assert transforms.shape == (len(keys), 2)
    assert (np.all(transforms[0] == transform_b)
            or np.all(transforms[2] == transform_b))

    # Check that the signal parameter slices are correct
    for (par, sl) in signal_parameter_slices:
        if par == conn_a:
            assert sl == set(range(0, 2)) or sl == set(range(1, 3))
        else:
            assert par == conn_b
            assert sl == set(range(0, 1)) or sl == set(range(2, 3))
예제 #9
0
def test_get_transforms_and_keys_removes_zeroed_rows(latching):
    """Check that zeroed rows (those that would always result in zero valued
    packets) are removed, and the keys miss this value as well.
    """
    ks = mock.Mock()
    transform = np.ones((10, 5))
    transform[1, :] = 0.0
    transform[4:7, :] = 0.0
    transform[:, 1] = 0.0

    # Create a signal and keyspace
    sig = mock.Mock()
    sig.keyspace = ks
    sig.latching = latching
    sig = SignalParameters(keyspace=ks, latching=latching)

    # Create a mock connection
    conn = PassthroughNodeTransmissionParameters(transform)

    signals_connections = [(sig, conn)]

    # Get the transform and keys
    t, keys, _ = get_transforms_and_keys(signals_connections)

    if not latching:
        # Check the transform is correct
        assert np.all(t ==
                      np.vstack((transform[0], transform[2:4], transform[7:])))

        # Check the keys were called for correctly
        ks.assert_has_calls([mock.call(index=0),
                             mock.call(index=2),
                             mock.call(index=3),
                             mock.call(index=7),
                             mock.call(index=8),
                             mock.call(index=9)])
    else:
        # Check the transform is correct
        assert np.all(t == t)

        # Check the keys were called for correctly
        ks.assert_has_calls([mock.call(index=0),
                             mock.call(index=1),
                             mock.call(index=2),
                             mock.call(index=3),
                             mock.call(index=4),
                             mock.call(index=5),
                             mock.call(index=6),
                             mock.call(index=7),
                             mock.call(index=8),
                             mock.call(index=9)])
예제 #10
0
def _combine_transmission_params(in_transmission_parameters,
                                 out_transmission_parameters, final_port):
    """Combine transmission parameters to join two signals into one, e.g., for
    optimising out a passthrough Node.

    Returns
    -------
    transmission_parameters
        New transmission parameters
    port
        New receiving port for the connection
    """
    assert isinstance(out_transmission_parameters,
                      PassthroughNodeTransmissionParameters)

    # Compute the new transform
    new_transform = np.dot(out_transmission_parameters.transform,
                           in_transmission_parameters.transform)

    # If the resultant transform is empty then we return None to indicate that
    # the connection should be dropped.
    if np.all(new_transform == 0.0):
        return None, None

    # If the connection is a global inhibition connection then truncate the
    # transform and modify the final port to reroute the connection.
    if (final_port is EnsembleInputPort.neurons
            and np.all(new_transform[0] == new_transform[1:])):
        # Truncate the transform
        new_transform = new_transform[0]
        new_transform.shape = (1, -1)  # Ensure the result is a matrix

        # Change the final port
        final_port = EnsembleInputPort.global_inhibition

    # Construct the new transmission parameters
    if isinstance(in_transmission_parameters, EnsembleTransmissionParameters):
        transmission_params = EnsembleTransmissionParameters(
            in_transmission_parameters.untransformed_decoders, new_transform)
    elif isinstance(in_transmission_parameters, NodeTransmissionParameters):
        transmission_params = NodeTransmissionParameters(
            in_transmission_parameters.pre_slice,
            in_transmission_parameters.function, new_transform)
    elif isinstance(in_transmission_parameters,
                    PassthroughNodeTransmissionParameters):
        transmission_params = PassthroughNodeTransmissionParameters(
            new_transform)
    else:
        raise NotImplementedError

    return transmission_params, final_port
    def test_unknown_to_x(self):
        # Create the ingoing connection parameters
        in_transmission_params = mock.Mock()
        in_transmission_params.transform = 1.0

        # Create the outgoing connection parameters
        out_transmission_params = PassthroughNodeTransmissionParameters(
            np.array([[0.0, 0.0], [0.0, 1.0]]))

        # Combine the parameter sets
        with pytest.raises(NotImplementedError):
            model_utils._combine_transmission_params(in_transmission_params,
                                                     out_transmission_params,
                                                     None)
    def test_ens_to_gi(self):
        # Create the ingoing connection parameters
        in_transmission_params = EnsembleTransmissionParameters(
            np.random.uniform(size=(100, 7)), 1.0)

        # Create the outgoing connection parameters
        out_transmission_params = PassthroughNodeTransmissionParameters(
            np.ones((200, 7)))

        # Combine the parameter sets
        new_tps, new_in_port = model_utils._combine_transmission_params(
            in_transmission_params, out_transmission_params,
            EnsembleInputPort.neurons)

        # Check that all the parameters are correct
        assert np.all(new_tps.transform == 1.0)
        assert new_tps.transform.shape == (1, 7)
        assert new_tps.decoders.shape == (1, 100)
        assert new_in_port is EnsembleInputPort.global_inhibition
    def test_ens_to_x(self, final_port):
        # Create the ingoing connection parameters
        in_transmission_params = EnsembleTransmissionParameters(
            np.random.uniform(size=(100, 10)), 1.0)

        # Create the outgoing connection parameters
        out_transmission_params = PassthroughNodeTransmissionParameters(
            np.hstack([np.eye(5), np.zeros((5, 5))]))

        # Combine the parameter sets
        new_tps, new_in_port = model_utils._combine_transmission_params(
            in_transmission_params, out_transmission_params, final_port)

        # Check that all the parameters are correct
        assert np.all(new_tps.untransformed_decoders ==
                      in_transmission_params.untransformed_decoders)
        assert np.all(new_tps.transform == out_transmission_params.transform)
        assert new_tps.decoders.shape == (5, 100)
        assert new_in_port is final_port
예제 #14
0
    def test_make_vertices_one_group_many_cores_1_chip(self):
        """Test that many vertices are returned if the matrix has many rows and
        that there is an appropriate constraint forcing the co-location of the
        vertices.
        """
        # Create a small filter operator
        filter_op = Filter(3)

        # Create a model and add some connections which will cause packets to
        # be transmitted from the filter operator.
        m = Model()
        signal_parameters = SignalParameters(False, 3, m.keyspaces["nengo"])
        signal_parameters.keyspace.length = 32

        transmission_parameters = PassthroughNodeTransmissionParameters(
            Transform(size_in=3, size_out=96, transform=np.ones((96, 3))))
        m.connection_map.add_connection(filter_op, OutputPort.standard,
                                        signal_parameters,
                                        transmission_parameters, None, None,
                                        None)

        # Make vertices using the model
        netlistspec = filter_op.make_vertices(m, 10000)
        assert len(netlistspec.vertices) == 2  # Two vertices

        for vx in netlistspec.vertices:
            assert "filter" in vx.application

            assert vx.resources[Cores] == 1

            assert vx.regions[Regions.system].column_slice == slice(0, 3)

            keys_region = vx.regions[Regions.keys]
            assert keys_region.signals_and_arguments == [
                (signal_parameters, dict(index=i)) for i in range(32 * 3)
            ]
            assert len(keys_region.fields) == 1
            assert keys_region.partitioned is True

            assert vx.regions[Regions.transform].matrix.shape == (32 * 3, 3)
def test_remove_operator_from_connection_map():
    """Test that operators are correctly removed from connection maps.

    We test the following model:

        O1 ------> O3 -----> O5
            /-----/  \
           /          \----> O6
        O2 --> O4

    Removing `O3' should result in:

        O1 --> O6
            /
           /-> 05
        O2 --> O4
    """
    # Construct the operators
    operators = [mock.Mock(name="O{}".format(i + 1)) for i in range(6)]

    # Create a connection map
    cm = model.ConnectionMap()

    # Add the connection O1 to O3
    sps = model.SignalParameters(True, 6)
    tps = PassthroughNodeTransmissionParameters(
        np.vstack([np.eye(3), np.zeros((3, 3))]))
    rps = model.ReceptionParameters(None, 6)

    cm.add_connection(source_object=operators[0],
                      source_port=None,
                      signal_parameters=sps,
                      transmission_parameters=tps,
                      sink_object=operators[2],
                      sink_port=None,
                      reception_parameters=rps)

    # Add the connection O2 to O3
    sps = model.SignalParameters(False, 6)
    tps = PassthroughNodeTransmissionParameters(
        np.vstack([np.zeros((3, 3)), np.eye(3)]))
    rps = model.ReceptionParameters(None, 6)

    cm.add_connection(source_object=operators[1],
                      source_port=None,
                      signal_parameters=sps,
                      transmission_parameters=tps,
                      sink_object=operators[2],
                      sink_port=None,
                      reception_parameters=rps)

    # Add the connection O2 to O4 (with a custom keyspace)
    sps = model.SignalParameters(False, 6, mock.Mock("Keyspace 1"))
    tps = PassthroughNodeTransmissionParameters(
        np.vstack([np.eye(3), np.eye(3)]))
    rps = model.ReceptionParameters(None, 6)

    cm.add_connection(source_object=operators[1],
                      source_port=None,
                      signal_parameters=sps,
                      transmission_parameters=tps,
                      sink_object=operators[3],
                      sink_port=None,
                      reception_parameters=rps)

    # Add the connection O3 to O5
    sps = model.SignalParameters(False, 3)
    tps = PassthroughNodeTransmissionParameters(
        np.hstack((np.zeros((3, 3)), np.eye(3))))
    rps = model.ReceptionParameters(None, 3)

    cm.add_connection(source_object=operators[2],
                      source_port=None,
                      signal_parameters=sps,
                      transmission_parameters=tps,
                      sink_object=operators[4],
                      sink_port=None,
                      reception_parameters=rps)

    # Add the connection O3 to O6
    sps = model.SignalParameters(False, 3)
    tps = PassthroughNodeTransmissionParameters(
        np.hstack([np.eye(3), np.eye(3)]) * 2)
    rps = model.ReceptionParameters(None, 3)

    cm.add_connection(source_object=operators[2],
                      source_port=None,
                      signal_parameters=sps,
                      transmission_parameters=tps,
                      sink_object=operators[5],
                      sink_port=None,
                      reception_parameters=rps)

    # Remove O3 from the connection map
    model_utils.remove_operator_from_connection_map(cm, operators[2])

    # Check that the received and transmitted signals are as expected
    # FROM O1
    from_o1 = cm._connections[operators[0]]
    assert len(from_o1) == 1
    assert len(from_o1[None]) == 1

    ((signal_parameters, transmission_parameters), sinks) = from_o1[None][0]
    assert signal_parameters == model.SignalParameters(True, 3, None)
    assert transmission_parameters.transform.shape == (3, 3)
    assert np.all(transmission_parameters.transform == np.eye(3) * 2)
    assert sinks == [(operators[5], None, model.ReceptionParameters(None, 3))]

    # FROM O2
    from_o2 = cm._connections[operators[1]]
    assert len(from_o2) == 1
    assert len(from_o2[None]) == 3

    for ((signal_parameters, transmission_parameters), sinks) in from_o2[None]:
        if transmission_parameters.transform.shape == (3, 3):
            assert (signal_parameters == model.SignalParameters(
                False, 3, None))

            if np.any(transmission_parameters.transform == 2.0):
                # TO O6
                assert np.all(transmission_parameters.transform == np.eye(3) *
                              2)
                assert sinks == [(operators[5], None,
                                  model.ReceptionParameters(None, 3))]
            else:
                # TO O5
                assert np.all(transmission_parameters.transform == np.eye(3))
                assert sinks == [(operators[4], None,
                                  model.ReceptionParameters(None, 3))]
        else:
            # TO O4
            assert transmission_parameters.transform.shape == (6, 3)
            assert np.all(
                transmission_parameters.transform == np.vstack([np.eye(3)] *
                                                               2))
            assert sinks == [(operators[3], None,
                              model.ReceptionParameters(None, 6))]

    # We now add a connection from O4 to O6 with a custom keyspace.  Removing
    # O4 will fail because keyspaces can't be merged.
    signal_params = model.SignalParameters(False, 1, mock.Mock("Keyspace 2"))
    transmission_params = PassthroughNodeTransmissionParameters(1.0)
    reception_params = model.ReceptionParameters(None, 1)

    cm.add_connection(source_object=operators[3],
                      source_port=None,
                      signal_parameters=signal_params,
                      transmission_parameters=transmission_params,
                      sink_object=operators[5],
                      sink_port=None,
                      reception_parameters=reception_params)

    with pytest.raises(NotImplementedError) as err:
        model_utils.remove_operator_from_connection_map(cm, operators[3])
    assert "keyspace" in str(err.value).lower()
def test_remove_operator_from_connection_map_unforced():
    """Check that a calculation is made to determine whether it is better to
    keep or remove an operator depending on the density of the outgoing
    connections. In the example:

                                               /- G[0]
        A[0] --\         /-- D[0] --\         /-- G[1]
        A[1] --- B --- C --- D[1] --- E --- F --- G[2]
        A[n] --/         \-- D[n] --/         \-- G[3]
                                               \- G[n]

    B, C and F should be removed but E should be retained:

                             /- G[0]
        A[0] --- D[0] --\   /-- G[1]
        A[1] --- D[1] --- E --- G[2]
        A[n] --- D[n] --/   \-- G[3]
                             \- G[n]
    """
    # Create the operators
    D = 512
    SD = 16

    op_A = [mock.Mock(name="A{}".format(i)) for i in range(D // SD)]
    op_B = mock.Mock(name="B")
    op_C = mock.Mock(name="C")
    op_D = [mock.Mock(name="D{}".format(i)) for i in range(D // SD)]
    op_E = mock.Mock(name="E")
    op_F = mock.Mock(name="F")
    op_G = [mock.Mock(name="G{}".format(i)) for i in range(D)]

    # Create a connection map
    cm = model.ConnectionMap()

    # Create the fan-in connections
    for sources, sink in ((op_A, op_B), (op_D, op_E)):
        # Get the signal and reception parameters
        sps = model.SignalParameters(True, D)
        rps = model.ReceptionParameters(None, D)

        for i, source in enumerate(sources):
            # Get the transform
            transform = np.zeros((D, SD))
            transform[i * SD:(i + 1) * SD, :] = np.eye(SD)

            # Get the parameters
            tps = EnsembleTransmissionParameters(np.ones((1, SD)), transform)

            cm.add_connection(source_object=source,
                              source_port=None,
                              signal_parameters=sps,
                              transmission_parameters=tps,
                              sink_object=sink,
                              sink_port=None,
                              reception_parameters=rps)

    # Create the fan-out connection C to D[...]
    # Get the signal and reception parameters
    sps = model.SignalParameters(True, SD)
    rps = model.ReceptionParameters(None, SD)

    for i, sink in enumerate(op_D):
        # Get the transform
        transform = np.zeros((SD, D))
        transform[:, i * SD:(i + 1) * SD] = np.eye(SD)

        # Get the parameters
        tps = PassthroughNodeTransmissionParameters(transform)

        cm.add_connection(source_object=op_C,
                          source_port=None,
                          signal_parameters=sps,
                          transmission_parameters=tps,
                          sink_object=sink,
                          sink_port=None,
                          reception_parameters=rps)

    # Create the connection B to C
    sps = model.SignalParameters(True, D)
    rps = model.ReceptionParameters(None, D)
    tps = PassthroughNodeTransmissionParameters(np.eye(D))

    cm.add_connection(source_object=op_B,
                      source_port=None,
                      signal_parameters=sps,
                      transmission_parameters=tps,
                      sink_object=op_C,
                      sink_port=None,
                      reception_parameters=rps)

    # Create the connection E to F
    transform = np.zeros((D, D))
    for i in range(D):
        for j in range(D):
            transform[i, j] = i + j

    sps = model.SignalParameters(True, D)
    rps = model.ReceptionParameters(None, D)
    tps = PassthroughNodeTransmissionParameters(transform)

    cm.add_connection(source_object=op_E,
                      source_port=None,
                      signal_parameters=sps,
                      transmission_parameters=tps,
                      sink_object=op_F,
                      sink_port=None,
                      reception_parameters=rps)

    # Create the fan-out connections from F
    sps = model.SignalParameters(True, SD)
    rps = model.ReceptionParameters(None, SD)

    for i, sink in enumerate(op_G):
        # Get the transform
        transform = np.zeros((1, D))
        transform[:, i] = 1.0

        # Get the parameters
        tps = PassthroughNodeTransmissionParameters(transform)

        cm.add_connection(source_object=op_F,
                          source_port=None,
                          signal_parameters=sps,
                          transmission_parameters=tps,
                          sink_object=sink,
                          sink_port=None,
                          reception_parameters=rps)

    # Remove all of the passthrough Nodes, only E should be retained
    assert model_utils.remove_operator_from_connection_map(cm,
                                                           op_B,
                                                           force=False)
    assert model_utils.remove_operator_from_connection_map(cm,
                                                           op_C,
                                                           force=False)
    assert not model_utils.remove_operator_from_connection_map(
        cm, op_E, force=False)
    assert model_utils.remove_operator_from_connection_map(cm,
                                                           op_F,
                                                           force=False)

    # Check that each A has only one outgoing signal and that it terminates at
    # the paired D.  Additionally check that each D has only one outgoing
    # signal and that it terminates at E.
    for a, d in zip(op_A, op_D):
        # Connections from A[n]
        from_a = cm._connections[a]
        assert len(from_a) == 1
        assert len(from_a[None]) == 1

        ((signal_parameters, transmission_parameters), sinks) = from_a[None][0]
        assert signal_parameters == model.SignalParameters(True, SD, None)
        assert transmission_parameters.transform.shape == (SD, SD)
        assert np.all(transmission_parameters.transform == np.eye(SD))
        assert sinks == [(d, None, model.ReceptionParameters(None, SD))]

        # Connection(s) from D[n]
        from_d = cm._connections[d]
        assert len(from_d) == 1
        assert len(from_d[None]) == 1

        ((signal_parameters, transmission_parameters), sinks) = from_d[None][0]
        assert signal_parameters == model.SignalParameters(True, D, None)
        assert transmission_parameters.transform.shape == (D, SD)

    # Check that there are many connections from E
    from_e = cm._connections[op_E]
    assert len(from_e) == 1
    print(from_e[None][0].parameters[1].transform)
    assert len(from_e[None]) == D