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}}
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
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)
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
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