def test_network_copy_reordered(dtype, num_charges): a = tn.Node(get_random_symmetric((30, 30, 30), [False, False, False], num_charges, dtype=dtype), backend='symmetric') b = tn.Node(get_random_symmetric((30, 30, 30), [False, True, False], num_charges, dtype=dtype), backend='symmetric') c = tn.Node(get_random_symmetric((30, 30, 30), [True, False, True], num_charges, dtype=dtype), backend='symmetric') a[0] ^ b[1] a[1] ^ c[2] b[2] ^ c[0] edge_order = [a[2], c[1], b[0]] node_dict, edge_dict = tn.copy({a, b, c}) tn.check_correct({a, b, c}) res = a @ b @ c res.reorder_edges(edge_order) res_copy = node_dict[a] @ node_dict[b] @ node_dict[c] res_copy.reorder_edges([edge_dict[e] for e in edge_order]) np.testing.assert_allclose(res.tensor.data, res_copy.tensor.data)
def test_node2_contract_trace(backend): a = tn.Node(np.zeros([3, 3, 1]), backend=backend) b = tn.Node(np.zeros([1]), backend=backend) tn.connect(b[0], a[2]) trace_edge = tn.connect(a[0], a[1]) c = tn.contract(trace_edge) tn.check_correct({c})
def test_split_node_mixed_order(dtype, num_charges): np.random.seed(111) a = tn.Node(get_zeros((2, 3, 4, 5, 6), num_charges, dtype), backend='symmetric') left_edges = [] for i in [0, 2, 4]: left_edges.append(a[i]) right_edges = [] for i in [1, 3]: right_edges.append(a[i]) left, right, _ = tn.split_node(a, left_edges, right_edges) tn.check_correct({left, right}) actual = left @ right np.testing.assert_allclose(actual.tensor.shape, (2, 4, 6, 3, 5)) np.testing.assert_allclose(a.tensor.shape, (2, 4, 6, 3, 5)) np.testing.assert_allclose(left.tensor.data, 0) np.testing.assert_allclose(right.tensor.data, 0) np.testing.assert_allclose(left.tensor.shape[0:3], (2, 4, 6)) np.testing.assert_allclose(right.tensor.shape[1:], (3, 5)) assert np.all([ charge_equal(a.tensor.charges[n][0], actual.tensor.charges[n][0]) for n in range(len(a.tensor._charges)) ])
def test_indirect_trace(backend): a = tn.Node(np.ones([10, 10]), name="a", backend=backend) edge = tn.connect(a[0], a[1], "edge") tn.check_correct({a}) val = tn.contract(edge) tn.check_correct({val}) np.testing.assert_allclose(val.tensor, 10.0)
def test_check_correct_raises_value_error_2(backend): a = tn.Node(np.random.rand(3, 3, 3), backend=backend) b = tn.Node(np.random.rand(3, 3, 3), backend=backend) edge = a.edges[0] edge.axis1 = -1 with pytest.raises(ValueError): tn.check_correct({a, b})
def test_small_matmul(backend): a = tn.Node(np.zeros([10, 10]), name="a", backend=backend) b = tn.Node(np.zeros([10, 10]), name="b", backend=backend) edge = tn.connect(a[0], b[0], "edge") tn.check_correct({a, b}) c = tn.contract(edge, name="a * b") assert list(c.shape) == [10, 10] tn.check_correct({c})
def test_contract_between_trace_edges(backend): a_val = np.ones((3, 3)) final_val = np.trace(a_val) a = tn.Node(a_val, backend=backend) tn.connect(a[0], a[1]) b = tn.contract_between(a, a) tn.check_correct({b}) np.testing.assert_allclose(b.tensor, final_val)
def test_contract_single_edge(backend): a = tn.Node(np.array([1.0] * 5), "a", backend=backend) b = tn.Node(np.array([1.0] * 5), "b", backend=backend) e = tn.connect(a[0], b[0]) c = tn.contract(e) tn.check_correct({c}) val = c.tensor np.testing.assert_allclose(val, 5.0)
def test_contract_between_trace_edges(dtype, num_charges): a_val = get_random_symmetric((50, 50), [False, True], num_charges, dtype=dtype) final_val = np.trace(a_val.todense()) a = tn.Node(a_val, backend='symmetric') tn.connect(a[0], a[1]) b = tn.contract_between(a, a) tn.check_correct({b}) np.testing.assert_allclose(b.tensor.todense(), final_val)
def test_flatten_trace_consistent_tensor(backend): a_val = np.ones((5, 3, 4, 4, 5)) a = tn.Node(a_val, backend=backend) e1 = tn.connect(a[0], a[4]) e2 = tn.connect(a[3], a[2]) tn.flatten_edges([e2, e1]) tn.check_correct({a}) # Check expected values. a_final = np.reshape(np.transpose(a_val, (1, 2, 0, 3, 4)), (3, 20, 20)) np.testing.assert_allclose(a.tensor, a_final)
def test_flatten_edges_between(backend): a = tn.Node(np.ones((3, 4, 5)), backend=backend) b = tn.Node(np.ones((5, 4, 3)), backend=backend) tn.connect(a[0], b[2]) tn.connect(a[1], b[1]) tn.connect(a[2], b[0]) tn.flatten_edges_between(a, b) tn.check_correct({a, b}) np.testing.assert_allclose(a.tensor, np.ones((60, ))) np.testing.assert_allclose(b.tensor, np.ones((60, )))
def test_split_node_qr(backend): a = tn.Node(np.random.rand(2, 3, 4, 5, 6), backend=backend) left_edges = [] for i in range(3): left_edges.append(a[i]) right_edges = [] for i in range(3, 5): right_edges.append(a[i]) left, right = tn.split_node_qr(a, left_edges, right_edges) tn.check_correct([left, right]) np.testing.assert_allclose(a.tensor, tn.contract(left[3]).tensor)
def test_flatten_edges_dangling(backend): a = tn.Node(np.zeros((2, 3, 4, 5)), name="A", backend=backend) e1 = a[0] e2 = a[1] e3 = a[2] e4 = a[3] flattened_edge = tn.flatten_edges([e1, e3], new_edge_name="New Edge") assert a.shape == (3, 5, 8) assert a.edges == [e2, e4, flattened_edge] assert flattened_edge.name == "New Edge" tn.check_correct({a})
def test_split_node_full_svd(backend): unitary1 = np.array([[1.0, 1.0], [1.0, -1.0]]) / np.sqrt(2.0) unitary2 = np.array([[0.0, 1.0], [1.0, 0.0]]) singular_values = np.array([9.1, 7.5], dtype=np.float32) val = np.dot(unitary1, np.dot(np.diag(singular_values), (unitary2.T))) a = tn.Node(val, backend=backend) e1 = a[0] e2 = a[1] _, s, _, _, = tn.split_node_full_svd(a, [e1], [e2]) tn.check_correct(tn.reachable(s)) np.testing.assert_allclose(s.tensor, np.diag([9.1, 7.5]), rtol=1e-5)
def test_reorder_axes(backend): a = tn.Node(np.zeros((2, 3, 4)), backend=backend) b = tn.Node(np.zeros((3, 4, 5)), backend=backend) c = tn.Node(np.zeros((2, 4, 5)), backend=backend) tn.connect(a[0], c[0]) tn.connect(b[0], a[1]) tn.connect(a[2], c[1]) tn.connect(b[2], c[2]) a.reorder_axes([2, 0, 1]) tn.check_correct({a, b, c}) assert a.shape == (4, 2, 3)
def test_flatten_trace_edges(backend): a = tn.Node(np.zeros((2, 3, 4, 3, 5, 5)), backend=backend) c = tn.Node(np.zeros((2, 4)), backend=backend) e1 = tn.connect(a[1], a[3]) e2 = tn.connect(a[4], a[5]) external_1 = tn.connect(a[0], c[0]) external_2 = tn.connect(c[1], a[2]) new_edge = tn.flatten_edges([e1, e2], "New Edge") tn.check_correct({a, c}) assert a.shape == (2, 4, 15, 15) assert a.edges == [external_1, external_2, new_edge, new_edge] assert new_edge.name == "New Edge"
def test_split_node_mixed_order(backend): a = tn.Node(np.zeros((2, 3, 4, 5, 6)), backend=backend) left_edges = [] for i in [0, 2, 4]: left_edges.append(a[i]) right_edges = [] for i in [1, 3]: right_edges.append(a[i]) left, right, _ = tn.split_node(a, left_edges, right_edges) tn.check_correct({left, right}) np.testing.assert_allclose(left.tensor, np.zeros((2, 4, 6, 15))) np.testing.assert_allclose(right.tensor, np.zeros((15, 3, 5)))
def test_split_edges_standard_contract_between(backend): a = tn.Node(np.random.randn(6, 3, 5), name="A", backend=backend) b = tn.Node(np.random.randn(2, 4, 6, 3), name="B", backend=backend) e1 = tn.connect(a[0], b[2], "Edge_1_1") # to be split tn.connect(a[1], b[3], "Edge_1_2") # background standard edge node_dict, _ = tn.copy({a, b}) c_prior = node_dict[a] @ node_dict[b] shape = (2, 1, 3) tn.split_edge(e1, shape) tn.check_correct({a, b}) c_post = tn.contract_between(a, b) np.testing.assert_allclose(c_prior.tensor, c_post.tensor)
def test_split_node(backend): a = tn.Node(np.zeros((2, 3, 4, 5, 6)), backend=backend) left_edges = [] for i in range(3): left_edges.append(a[i]) right_edges = [] for i in range(3, 5): right_edges.append(a[i]) left, right, _ = tn.split_node(a, left_edges, right_edges) tn.check_correct({left, right}) np.testing.assert_allclose(left.tensor, np.zeros((2, 3, 4, 24))) np.testing.assert_allclose(right.tensor, np.zeros((24, 5, 6)))
def test_node_edge_ordering(backend): a = tn.Node(np.zeros((2, 3, 4)), backend=backend) e2 = a[0] e3 = a[1] e4 = a[2] assert a.shape == (2, 3, 4) a.reorder_edges([e4, e2, e3]) tn.check_correct({a}) assert a.shape == (4, 2, 3) assert e2.axis1 == 1 assert e3.axis1 == 2 assert e4.axis1 == 0
def test_small_matmul(dtype, num_charges): a = tn.Node( get_random_symmetric((100, 100), [True, True], num_charges, dtype=dtype), backend='symmetric') b = tn.Node( get_random_symmetric((100, 100), [False, True], num_charges, dtype=dtype), backend='symmetric') edge = tn.connect(a[0], b[0], "edge") tn.check_correct({a, b}) c = tn.contract(edge, name="a * b") assert list(c.shape) == [100, 100] tn.check_correct({c})
def test_outer_product(backend): a = tn.Node(np.ones((2, 4, 5)), name="A", backend=backend) b = tn.Node(np.ones((4, 3, 6)), name="B", backend=backend) c = tn.Node(np.ones((3, 2)), name="C", backend=backend) tn.connect(a[1], b[0]) tn.connect(a[0], c[1]) tn.connect(b[1], c[0]) # Purposely leave b's 3rd axis undefined. d = tn.outer_product(a, b, name="D") tn.check_correct({c, d}) assert d.shape == (2, 4, 5, 4, 3, 6) np.testing.assert_allclose(d.tensor, np.ones((2, 4, 5, 4, 3, 6))) assert d.name == "D"
def test_tnwork_copy(backend): a = tn.Node(np.random.rand(3, 3, 3), backend=backend) b = tn.Node(np.random.rand(3, 3, 3), backend=backend) c = tn.Node(np.random.rand(3, 3, 3), backend=backend) a[0] ^ b[1] a[1] ^ c[2] b[2] ^ c[0] node_dict, _ = tn.copy({a, b, c}) tn.check_correct({node_dict[n] for n in {a, b, c}}) res = a @ b @ c res_copy = node_dict[a] @ node_dict[b] @ node_dict[c] np.testing.assert_allclose(res.tensor, res_copy.tensor)
def test_complicated_edge_reordering(backend): a = tn.Node(np.zeros((2, 3, 4)), backend=backend) b = tn.Node(np.zeros((2, 5)), backend=backend) c = tn.Node(np.zeros((3, )), backend=backend) d = tn.Node(np.zeros((4, 5)), backend=backend) e_ab = tn.connect(a[0], b[0]) e_bd = tn.connect(b[1], d[1]) e_ac = tn.connect(a[1], c[0]) e_ad = tn.connect(a[2], d[0]) result = tn.contract(e_bd) a.reorder_edges([e_ac, e_ab, e_ad]) tn.check_correct(tn.reachable(result)) assert a.shape == (3, 2, 4)
def test_flatten_edges_standard(backend): a = tn.Node(np.zeros((2, 3, 5)), name="A", backend=backend) b = tn.Node(np.zeros((2, 3, 4, 5)), name="B", backend=backend) e1 = tn.connect(a[0], b[0], "Edge_1_1") e2 = tn.connect(a[2], b[3], "Edge_2_3") edge_a_1 = a[1] edge_b_1 = b[1] edge_b_2 = b[2] new_edge = tn.flatten_edges([e1, e2], new_edge_name="New Edge") assert a.shape == (3, 10) assert b.shape == (3, 4, 10) assert a.edges == [edge_a_1, new_edge] assert b.edges == [edge_b_1, edge_b_2, new_edge] tn.check_correct({a, b})
def test_flatten_trace_consistent_tensor(dtype, num_charges): a_val = get_random_symmetric((5, 5, 5, 5, 5), [False, False, True, True, True], num_charges, dtype=dtype) a = tn.Node(a_val, backend='symmetric') e1 = tn.connect(a[0], a[4]) e2 = tn.connect(a[3], a[2]) tn.flatten_edges([e2, e1]) tn.check_correct({a}) # Check expected values. a_final = np.reshape(np.transpose(a_val.todense(), (1, 2, 0, 3, 4)), (5, 25, 25)) np.testing.assert_allclose(a.tensor.todense(), a_final)
def test_node2_contract_trace(dtype, num_charges): a = tn.Node(get_random_symmetric((20, 20, 20), [False, True, False], num_charges, dtype=dtype), backend='symmetric') b = tn.Node(get_random_symmetric((20, 20), [True, False], num_charges, dtype=dtype), backend='symmetric') tn.connect(b[0], a[2]) trace_edge = tn.connect(a[0], a[1]) c = tn.contract(trace_edge) tn.check_correct({c})
def test_real_physics_with_tensors(backend): # Calcuate the expected value in numpy a_vals = np.ones([2, 3, 4, 5]) b_vals = np.ones([4, 6, 7]) c_vals = np.ones([5, 6, 8]) contract1 = np.tensordot(a_vals, b_vals, [[2], [0]]) contract2 = np.tensordot(c_vals, contract1, [[0], [2]]) final_result = np.trace(contract2, axis1=0, axis2=4) # Build the network a = tn.Node(np.ones([2, 3, 4, 5]), name="T", backend=backend) b = tn.Node(np.ones([4, 6, 7]), name="A", backend=backend) c = tn.Node(np.ones([5, 6, 8]), name="B", backend=backend) e1 = tn.connect(a[2], b[0], "edge") e2 = tn.connect(c[0], a[3], "edge2") e3 = tn.connect(b[1], c[1], "edge3") tn.check_correct({a, b, c}) node_result = tn.contract(e1) np.testing.assert_allclose(node_result.tensor, contract1) tn.check_correct(tn.reachable(node_result)) node_result = tn.contract(e2) np.testing.assert_allclose(node_result.tensor, contract2) tn.check_correct(tn.reachable(node_result)) val = tn.contract(e3) tn.check_correct(tn.reachable(val)) np.testing.assert_allclose(val.tensor, final_result)
def test_disconnect(backend): n1 = Node(np.random.rand(2), backend=backend) n2 = Node(np.random.rand(2), backend=backend) e = n1[0] ^ n2[0] assert not e.is_dangling() dangling_edge_1, dangling_edge_2 = e.disconnect('left_name', 'right_name') tn.check_correct([n1, n2], False) assert dangling_edge_1.is_dangling() assert dangling_edge_2.is_dangling() assert n1[0].is_dangling() assert n2[0].is_dangling() assert n1[0].name == 'left_name' assert n2[0].name == 'right_name' assert n1.get_edge(0) == dangling_edge_1 assert n2.get_edge(0) == dangling_edge_2
def test_split_edges_dangling(backend): a = tn.Node(np.zeros((2, 10, 4, 5)), name="A", backend=backend) e1 = a[0] e2 = a[1] e3 = a[2] e4 = a[3] shape = (2, 5) new_edge_names = ["New Edge 2", "New Edge 5"] new_edges = tn.split_edge(e2, shape, new_edge_names) assert a.shape == (2, 4, 5, 2, 5) assert a.edges == [e1, e3, e4, *new_edges] for new_edge, dim in zip(new_edges, shape): assert new_edge.dimension == dim for new_edge, new_name in zip(new_edges, new_edge_names): assert new_edge.name == new_name tn.check_correct({a})