def add_cnot(net: network.TensorNetwork, q0: network_components.Edge,
             q1: network_components.Edge
            ) -> Tuple[network_components.CopyNode, network_components
                       .Edge, network_components.Edge]:
  """Adds the CNOT quantum gate to tensor network.

  CNOT consists of two rank-3 tensors: a COPY tensor on the control qubit and
  a XOR tensor on the target qubit.

  Args:
    net: Tensor network to add CNOT to.
    q0: Input edge for the control qubit.
    q1: Input edge for the target qubit.

  Returns:
    Tuple with three elements:
    - copy tensor corresponding to the control qubit
    - output edge for the control qubit and
    - output edge for the target qubit.
  """
  control = net.add_copy_node(rank=3, dimension=2)
  xor = np.array([[[1, 0], [0, 1]], [[0, 1], [1, 0]]], dtype=np.float64)
  target = net.add_node(xor)
  net.connect(q0, control[0])
  net.connect(q1, target[0])
  net.connect(control[1], target[1])
  return control, control[2], target[2]
def test_backend_network(backend):
    a = np.random.randn(2, 2, 2)
    nodes, _, _ = ncon_interface.ncon_network([a, a, a],
                                              [(-1, 1, 2), (1, 2, 3),
                                               (3, -2, -3)],
                                              backend=backend)

    net = TensorNetwork(backend=backend)
    # pylint: disable=expression-not-assigned
    [net.add_node(n) for n in nodes]
    res = naive(net).get_final_node().tensor
    res_np = a.reshape((2, 4)) @ a.reshape((4, 2)) @ a.reshape((2, 4))
    res_np = res_np.reshape((2, 2, 2))
    np.testing.assert_allclose(res, res_np)