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.

  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.
  """
    #TODO: add support for copying CopyTensor
    if conjugate:
        node_dict = {
            node: Node(node.backend.conj(node.tensor),
                       name=node.name,
                       axis_names=node.axis_names,
                       backend=node.backend.name)
            for node in nodes
        }
    else:
        node_dict = {
            node: Node(node.tensor,
                       name=node.name,
                       axis_names=node.axis_names,
                       backend=node.backend.name)
            for node in nodes
        }
    edge_dict = {}
    for edge in get_all_edges(nodes):
        node1 = edge.node1
        axis1 = edge.node1.get_axis_number(edge.axis1)

        if not edge.is_dangling():
            node2 = edge.node2
            axis2 = edge.node2.get_axis_number(edge.axis2)
            new_edge = Edge(node_dict[node1], axis1, edge.name,
                            node_dict[node2], axis2)
            new_edge.set_signature(edge.signature)
        else:
            new_edge = Edge(node_dict[node1], axis1, edge.name)

        node_dict[node1].add_edge(new_edge, axis1)
        if not edge.is_dangling():
            node_dict[node2].add_edge(new_edge, axis2)
        edge_dict[edge] = new_edge
    return node_dict, edge_dict
Exemple #2
0
def copy(nodes: Iterable[BaseNode],
         conjugate: bool = False) -> Tuple[dict, dict]:
  """Copy the given nodes and their edges.

  This will return a tuple 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:
    node_dict[node] = node.copy(conjugate)
  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