Repository: google/TensorNetwork

Issue:
Add conj option to net.copy()
For calculating norms and reduced density matrices, it would be nice to be able to do `net.copy(conj=True)` to conjugate all of the nodes.

We already have conj built into the backends https://github.com/google/TensorNetwork/blob/af16c219e3cc1a411c89314648eb059000c378b8/tensornetwork/backends/base_backend.py#L268 so we can simply use that.




Discussion:
@Thenerdstation Can I work on this issue? Can you also explain a little more about it?
Certainly!

So the `net.copy()` operation in `TensorNetwork` currently uses the exact same Tensors when copying the network. We want to add an operation to conjugate the Tensors if the user requests it. So you would need to add an optional `conj` argument to the copy function that defaults to False and basically use `self.backend.conj(node.tensor)` instead of just `node.tensor` when copying a node.

Be sure to add a test! (You'll need to also skip the Pytorch backend in that test since complex numbers are not supported in Pytorch). 
only skip it though for complex data types.
Yes good point.

It might also be a good idea to have a `complex_data_test` once https://github.com/google/TensorNetwork/pull/222 is in that just doesn't have Pytorch as a backend.

Resolving patch:
diff --git a/tensornetwork/network.py b/tensornetwork/network.py
--- a/tensornetwork/network.py
+++ b/tensornetwork/network.py
@@ -76,24 +76,36 @@ def _new_node_name(self, name: Optional[Text]) -> Text:
   def dtype(self) -> Type[np.number]:
     return self.backend.dtype
 
-  def copy(self) -> Tuple["TensorNetwork", dict, dict]:
+  def copy(self, conj: bool = False) -> Tuple["TensorNetwork", dict, dict]:
     """
+
     Return a copy of the TensorNetwork.
+    Args:
+      conj: Boolean. Whether to conjugate all of the nodes in the
+        `TensorNetwork` (useful for calculating norms and reduced density
+        matrices).
     Returns:
       A tuple containing:
         TensorNetwork: A copy of the network.
-        node_dict: A dictionary mapping the nodes of the original 
+        node_dict: A dictionary mapping the nodes of the original
                    network to the nodes of the copy.
-        edge_dict: A dictionary mapping the edges of the original 
+        edge_dict: A dictionary mapping the edges of the original
                    network to the edges of the copy.
     """
     new_net = TensorNetwork(backend=self.backend.name)
     #TODO: add support for copying CopyTensor
-    node_dict = {
-        node: new_net.add_node(
-            node.tensor, name=node.name, axis_names=node.axis_names)
-        for node in self.nodes_set
-    }
+    if conj:
+      node_dict = {
+          node: new_net.add_node(
+              self.backend.conj(node.tensor), name=node.name, axis_names=node.axis_names)
+          for node in self.nodes_set
+      }
+    else:
+      node_dict = {
+          node: new_net.add_node(
+              node.tensor, name=node.name, axis_names=node.axis_names)
+          for node in self.nodes_set
+      }
     edge_dict = {}
     for edge in self.get_all_edges():
       node1 = edge.node1


Test patch:
diff --git a/tensornetwork/tests/network_test.py b/tensornetwork/tests/network_test.py
--- a/tensornetwork/tests/network_test.py
+++ b/tensornetwork/tests/network_test.py
@@ -72,6 +72,16 @@ def test_dtype(backend):
   assert net.dtype is None
 
 
+def test_network_copy_conj(backend):
+  if backend == "pytorch":
+    pytest.skip("Pytorch does not support complex numbers")
+  net = tensornetwork.TensorNetwork(backend=backend)
+  a = net.add_node(np.array([1.0 + 2.0j, 2.0 - 1.0j]))
+  _, nodes, _ = net.copy(conj=True)
+  np.testing.assert_allclose(
+      nodes[a].tensor, np.array([1.0 - 2.0j, 2.0 + 1.0j]))
+
+
 def test_network_copy(backend):
   net = tensornetwork.TensorNetwork(backend=backend)
   a = net.add_node(np.random.rand(3, 3, 3))
@@ -80,7 +90,6 @@ def test_network_copy(backend):
   a[0] ^ b[1]
   a[1] ^ c[2]
   b[2] ^ c[0]
-
   net_copy, node_dict, _ = net.copy()
   net_copy.check_correct()