def test_copy_node_get_partners_with_trace(backend):
  node1 = CopyNode(4, 2, backend=backend)
  node2 = Node(np.random.rand(2, 2), backend=backend, name="node2")
  tn.connect(node1[0], node1[1])
  tn.connect(node1[2], node2[0])
  tn.connect(node1[3], node2[1])
  assert node1.get_partners() == {node2: {0, 1}}
Beispiel #2
0
    def contract_copy_node(
            self,
            copy_node: network_components.CopyNode,
            name: Optional[Text] = None) -> network_components.BaseNode:
        """Contract all edges incident on given copy node.

    Args:
      copy_node: Copy tensor node to be contracted.
      name: Name of the new node created.

    Returns:
      New node representing contracted tensor.

    Raises:
      ValueError: If copy_node has dangling edge(s).
    """
        partners = copy_node.get_partners()
        new_node = self.add_node(
            network_components.contract_copy_node(copy_node, name))
        # Remove nodes
        for partner in partners:
            if partner in self.nodes_set:
                self.nodes_set.remove(partner)
        for partner in partners:
            if not partner.is_disabled:
                partner.disable()

        self.nodes_set.remove(copy_node)
        copy_node.disable()
        return new_node
def test_copy_node_load(tmp_path, backend):
  node = tn.CopyNode(
      rank=4,
      dimension=3,
      name='copier',
      axis_names=[str(n) for n in range(4)],
      backend=backend)
  with h5py.File(tmp_path / 'node', 'w') as node_file:
    node_group = node_file.create_group('node_data')
    node_group.create_dataset('signature', data=node.signature)
    node_group.create_dataset('backend', data=node.backend.name)
    node_group.create_dataset(
        'copy_node_dtype', data=np.dtype(node.copy_node_dtype).name)
    node_group.create_dataset('name', data=node.name)
    node_group.create_dataset('shape', data=node.shape)
    node_group.create_dataset(
        'axis_names',
        data=np.array(node.axis_names, dtype=object),
        dtype=string_type)
    node_group.create_dataset(
        'edges',
        data=np.array([edge.name for edge in node.edges], dtype=object),
        dtype=string_type)

    loaded_node = CopyNode._load_node(node_data=node_file["node_data/"])
    assert loaded_node.name == node.name
    assert loaded_node.signature == node.signature
    assert set(loaded_node.axis_names) == set(node.axis_names)
    assert (set(edge.name for edge in loaded_node.edges) == set(
        edge.name for edge in node.edges))
    assert loaded_node.get_dimension(axis=1) == node.get_dimension(axis=1)
    assert loaded_node.get_rank() == node.get_rank()
    assert loaded_node.shape == node.shape
    assert loaded_node.copy_node_dtype == node.copy_node_dtype
Beispiel #4
0
def test_copy_node_load(tmp_path, backend):
    net = tensornetwork.TensorNetwork(backend)
    node = net.add_copy_node(rank=4, dimension=3, name='copier')
    with h5py.File(tmp_path / 'node', 'w') as node_file:
        node_group = node_file.create_group('node_data')
        node_group.create_dataset('signature', data=node.signature)
        node_group.create_dataset('name', data=node.name)
        node_group.create_dataset('shape', data=node.shape)
        node_group.create_dataset('axis_names',
                                  data=np.array(node.axis_names, dtype=object),
                                  dtype=string_type)
        node_group.create_dataset('edges',
                                  data=np.array(
                                      [edge.name for edge in node.edges],
                                      dtype=object),
                                  dtype=string_type)
        net = tensornetwork.TensorNetwork(backend=node.network.backend.name)
        loaded_node = CopyNode._load_node(net, node_file["node_data/"])
        assert loaded_node.name == node.name
        assert loaded_node.signature == node.signature
        assert set(loaded_node.axis_names) == set(node.axis_names)
        assert (set(edge.name for edge in loaded_node.edges) == set(
            edge.name for edge in node.edges))
        assert loaded_node.get_dimension(axis=1) == node.get_dimension(axis=1)
        assert loaded_node.get_rank() == node.get_rank()
        assert loaded_node.shape == node.shape
def fixture_copy_node(backend):
    net = tensornetwork.TensorNetwork(backend=backend)
    return CopyNode(4,
                    2,
                    "copier", ["a", "b", "c", "d"],
                    network=net,
                    backend=backend)
Beispiel #6
0
    def contract_copy_node(
            self,
            copy_node: network_components.CopyNode,
            name: Optional[Text] = None) -> network_components.Node:
        """Contract all edges incident on given copy node.

    Args:
      copy_node: Copy tensor node to be contracted.
      name: Name of the new node created.

    Returns:
      New node representing contracted tensor.

    Raises:
      ValueError: If copy_node has dangling edge(s).
    """
        new_tensor = copy_node.compute_contracted_tensor()
        new_node = self.add_node(new_tensor, name)

        partners = copy_node.get_partners()
        new_axis = 0
        for partner in partners:
            for edge in partner.edges:
                if edge.node1 is copy_node or edge.node2 is copy_node:
                    self.edge_order.remove(edge)
                    continue
                old_axis = edge.axis1 if edge.node1 is partner else edge.axis2
                edge.update_axis(old_node=partner,
                                 old_axis=old_axis,
                                 new_node=new_node,
                                 new_axis=new_axis)
                new_node.add_edge(edge, new_axis)
                new_axis += 1
            self.nodes_set.remove(partner)
        assert len(new_tensor.shape) == new_axis

        self.nodes_set.remove(copy_node)
        self.nodes_set.add(new_node)
        return new_node
Beispiel #7
0
def identity(space: Sequence[int],
             backend: Optional[Text] = None,
             dtype: Type[np.number] = np.float64) -> "QuOperator":
    """Construct a `QuOperator` representing the identity on a given space.

  Internally, this is done by constructing `CopyNode`s for each edge, with
  dimension according to `space`.

  Args:
    space: A sequence of integers for the dimensions of the tensor product
      factors of the space (the edges in the tensor network).
    backend: Optionally specify the backend to use for computations.
    dtype: The data type (for conversion to dense).
  Returns:
    The desired identity operator.
  """
    nodes = [CopyNode(2, d, backend=backend, dtype=dtype) for d in space]
    out_edges = [n[0] for n in nodes]
    in_edges = [n[1] for n in nodes]
    return quantum_constructor(out_edges, in_edges)
def fixture_copy_node(backend):
  return CopyNode(4, 2, "copier", ["a", "b", "c", "d"], backend=backend)
def copy(nodes: Iterable[BaseNode],
         conjugate: bool = False) -> Tuple[dict, dict]:
    """Copy the given nodes and their edges.

  This will return a dictionary linking original nodes/edges 
  to their copies. If nodes A and B are connected but only A is passed in to be
  copied, the edge between them will become a dangling edge.

  Args:
    nodes: An `Iterable` (Usually a `List` or `Set`) of `Nodes`.
    conjugate: Boolean. Whether to conjugate all of the nodes
        (useful for calculating norms and reduced density
        matrices).

  Returns:
    A tuple containing:
      node_dict: A dictionary mapping the nodes to their copies.
      edge_dict: A dictionary mapping the edges to their copies.
  """
    node_dict = {}
    for node in nodes:
        if isinstance(node, CopyNode):
            node_dict[node] = CopyNode(node.rank,
                                       node.dimension,
                                       name=node.name,
                                       axis_names=node.axis_names,
                                       backend=node.backend,
                                       dtype=node.dtype)
        else:
            if conjugate:
                node_dict[node] = Node(node.backend.conj(node.tensor),
                                       name=node.name,
                                       axis_names=node.axis_names,
                                       backend=node.backend)
            else:
                node_dict[node] = Node(node.tensor,
                                       name=node.name,
                                       axis_names=node.axis_names,
                                       backend=node.backend)
    edge_dict = {}
    for edge in get_all_edges(nodes):
        node1 = edge.node1
        axis1 = edge.node1.get_axis_number(edge.axis1)
        # edge dangling or node2 does not need to be copied
        if edge.is_dangling() or edge.node2 not in node_dict:
            new_edge = Edge(node_dict[node1], axis1, edge.name)
            node_dict[node1].add_edge(new_edge, axis1)
            edge_dict[edge] = new_edge
            continue

        node2 = edge.node2
        axis2 = edge.node2.get_axis_number(edge.axis2)
        # copy node2 but not node1
        if node1 not in node_dict:
            new_edge = Edge(node_dict[node2], axis2, edge.name)
            node_dict[node2].add_edge(new_edge, axis2)
            edge_dict[edge] = new_edge
            continue

        # both nodes should be copied
        new_edge = Edge(node_dict[node1], axis1, edge.name, node_dict[node2],
                        axis2)
        new_edge.set_signature(edge.signature)
        node_dict[node2].add_edge(new_edge, axis2)
        node_dict[node1].add_edge(new_edge, axis1)
        edge_dict[edge] = new_edge

    return node_dict, edge_dict