Example #1
0
def test_get_all_nondangling(backend):
    a = tn.Node(np.eye(2), backend=backend)
    b = tn.Node(np.eye(2), backend=backend)
    edge1 = tn.connect(a[0], b[0])
    c = tn.Node(np.eye(2), backend=backend)
    d = tn.Node(np.eye(2), backend=backend)
    edge2 = tn.connect(c[0], d[0])
    edge3 = tn.connect(a[1], c[1])
    assert {edge1, edge2, edge3} == tn.get_all_nondangling({a, b, c, d})
Example #2
0
def test_get_shared_edges(backend):
  a = tn.Node(np.ones((2, 2, 2)), backend=backend)
  b = tn.Node(np.ones((2, 2, 2)), backend=backend)
  c = tn.Node(np.ones((2, 2, 2)), backend=backend)
  e1 = tn.connect(a[0], b[0])
  e2 = tn.connect(b[1], c[1])
  e3 = tn.connect(a[2], b[2])
  assert tn.get_shared_edges(a, b) == {e1, e3}
  assert tn.get_shared_edges(b, c) == {e2}
Example #3
0
def _apply_op_network(site_edges, op, n1, pbc=False):
    N = len(site_edges)
    op_sites = len(op.shape) // 2
    n_op = tensornetwork.Node(op, backend="tensorflow")
    for m in range(op_sites):
        target_site = (n1 + m) % N if pbc else n1 + m
        tensornetwork.connect(n_op[op_sites + m], site_edges[target_site])
        site_edges[target_site] = n_op[m]
    return site_edges, n_op
Example #4
0
def test_check_connected_value_error(backend):
    a = tn.Node(np.array([2, 2.]), backend=backend)
    b = tn.Node(np.array([2, 2.]), backend=backend)
    tn.connect(a[0], b[0])
    c = tn.Node(np.array([2, 2.]), backend=backend)
    d = tn.Node(np.array([2, 2.]), backend=backend)
    tn.connect(c[0], d[0])
    with pytest.raises(ValueError):
        tn.check_connected({a, b, c, d})
Example #5
0
def test_flatten_edges_different_nodes_value_error(backend):
    a = tn.Node(np.eye(2), backend=backend)
    b = tn.Node(np.eye(2), backend=backend)
    c = tn.Node(np.eye(2), backend=backend)
    e1 = tn.connect(a[0], b[0])
    e2 = tn.connect(a[1], c[0])
    tn.connect(b[1], c[1])
    with pytest.raises(ValueError):
        tn.flatten_edges([e1, e2])
def test_reachable_2(backend):
    a = tn.Node(np.zeros((3, 5)), backend=backend)
    b = tn.Node(np.zeros((3, 4, 5)), backend=backend)
    e1 = tn.connect(a[0], b[0])
    e2 = tn.connect(a[1], b[2])
    nodes = [a, b]
    edges = [e1, e2]
    assert set(nodes) == tn.reachable(edges[0])
    assert set(nodes) == tn.reachable(edges)
Example #7
0
def test_mixed_named_axis(backend):
    a = tn.Node(np.eye(2) * 2.0, axis_names=["alpha", "beta"], backend=backend)
    b = tn.Node(np.eye(2) * 3.0, backend=backend)
    e1 = tn.connect(a["alpha"], b[0])
    # Axes should still be indexable by numbers even with naming.
    e2 = tn.connect(a[1], b[1])
    tn.contract(e1)
    result = tn.contract(e2)
    np.testing.assert_allclose(result.tensor, 12.0)
Example #8
0
def test_double_trace(backend):
    a = tn.Node(np.ones([10, 10, 10, 10]), name="a", backend=backend)
    edge1 = tn.connect(a[0], a[1], "edge1")
    edge2 = tn.connect(a[2], a[3], "edge2")
    tn.check_correct({a})
    val = tn.contract(edge1)
    tn.check_correct({val})
    val = tn.contract(edge2)
    tn.check_correct({val})
    np.testing.assert_allclose(val.tensor, 100.0)
Example #9
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)
Example #10
0
def test_contract_between_trace_output_edge_order(backend):
    a_val = np.ones((2, 3, 2, 4))
    a = tn.Node(a_val, backend=backend)
    tn.connect(a[0], a[2])
    c = tn.contract_between(a,
                            a,
                            output_edge_order=[a[3], a[1]],
                            axis_names=["3", "1"])
    assert c.shape == (4, 3)
    assert c.axis_names == ["3", "1"]
Example #11
0
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)
Example #12
0
def test_replicate_nodes(backend):
    a = tn.Node(np.random.rand(10, 10), backend=backend)
    b = tn.Node(np.random.rand(10, 10), backend=backend)
    c = tn.Node(np.random.rand(10, 10), backend=backend)
    tn.connect(a[1], b[0])
    tn.connect(b[1], c[0])
    [a_copy, b_copy] = tn.replicate_nodes([a, b])
    assert b_copy in tn.reachable([a_copy])
    assert not set([a_copy, b_copy]).issubset(tn.reachable([c]))
    assert len(b_copy.get_all_dangling()) == 1
Example #13
0
def test_remove_node_trace_edge(backend):
    a = tn.Node(np.ones((2, 2, 2)), backend=backend)
    b = tn.Node(np.ones(2), backend=backend)
    tn.connect(a[0], b[0])
    tn.connect(a[1], a[2])
    _, broken_edges = tn.remove_node(a)
    assert 0 in broken_edges
    assert 1 not in broken_edges
    assert 2 not in broken_edges
    assert broken_edges[0] is b[0]
Example #14
0
    def _ev_mps(self, obs_nodes, wires):
        r"""Expectation value of observables on specified wires using a MPS representation.

         Args:
            obs_nodes (Sequence[tn.Node]): the observables as TensorNetwork Nodes
            wires (Sequence[Sequence[int]]): measured subsystems for each observable
         Returns:
            complex: expectation value :math:`\expect{A} = \bra{\psi}A\ket{\psi}`
        """
        if any(len(wires_seq) > 2 for wires_seq in wires):
            raise NotImplementedError(
                "Multi-wire measurement only supported for nearest-neighbour wire pairs."
            )
        if len(obs_nodes) == 1 and len(wires[0]) == 1:
            # TODO: can measure multiple local expectation values at once,
            # but this would require change of `expval` behaviour and
            # refactor of `execute` logic from parent class
            expval = self.mps.measure_local_operator(obs_nodes, wires[0])[0]
        else:
            conj_nodes = [tn.conj(node) for node in self.mps.nodes]
            meas_wires = []
            # connect measured bra and ket nodes with observables
            for obs_node, wire_seq in zip(obs_nodes, wires):
                if len(wire_seq) == 2 and abs(wire_seq[0] - wire_seq[1]) > 1:
                    raise NotImplementedError(
                        "Multi-wire measurement only supported for nearest-neighbour wire pairs."
                    )
                offset = len(wire_seq)
                for idx, wire in enumerate(wire_seq):
                    tn.connect(conj_nodes[wire][1], obs_node[idx])
                    tn.connect(obs_node[offset + idx], self.mps.nodes[wire][1])
                meas_wires.extend(wire_seq)
            for wire in range(self.num_wires):
                # connect unmeasured ket nodes with bra nodes
                if wire not in meas_wires:
                    tn.connect(conj_nodes[wire][1], self.mps.nodes[wire][1])
                # connect local nodes of MPS (not connected by default in tn)
                if wire != self.num_wires - 1:
                    tn.connect(self.mps.nodes[wire][2], self.mps.nodes[wire + 1][0])
                    tn.connect(conj_nodes[wire][2], conj_nodes[wire + 1][0])

            # contract MPS bonds first
            bra_node = conj_nodes[0]
            ket_node = self.mps.nodes[0]
            for wire in range(self.num_wires - 1):
                bra_node = tn.contract_between(bra_node, conj_nodes[wire + 1])
                ket_node = tn.contract_between(ket_node, self.mps.nodes[wire + 1])
            # contract observables into ket
            for obs_node in obs_nodes:
                ket_node = tn.contract_between(obs_node, ket_node)
            # contract bra into observables/ket
            expval_node = tn.contract_between(bra_node, ket_node)
            # remove dangling singleton edges
            expval = self._squeeze(expval_node.tensor)
        return expval
Example #15
0
def test_with_tensors(backend):
    a = tn.Node(np.eye(2) * 2, name="T", backend=backend)
    b = tn.Node(np.eye(2) * 3, name="A", backend=backend)
    e1 = tn.connect(a[0], b[0], "edge")
    e2 = tn.connect(a[1], b[1], "edge2")
    tn.check_correct({a, b})
    result = tn.contract(e1)
    tn.check_correct(tn.reachable(result))
    val = tn.contract(e2)
    tn.check_correct(tn.reachable(val))
    np.testing.assert_allclose(val.tensor, 12.0)
def test_at_operator(dtype, num_charges):
  a = tn.Node(
      get_random_symmetric((50, 50), [False, True], num_charges, dtype=dtype),
      backend='symmetric')
  b = tn.Node(
      get_random_symmetric((50, 50), [False, True], num_charges, dtype=dtype),
      backend='symmetric')
  tn.connect(a[1], b[0])
  c = a @ b
  assert isinstance(c, tn.Node)
  np.testing.assert_allclose(c.tensor.todense(),
                             a.tensor.todense() @ b.tensor.todense())
Example #17
0
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"
Example #18
0
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)
Example #19
0
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)
Example #20
0
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)
Example #21
0
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})
Example #22
0
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 fixture_double_node_edge(backend):
    tensor = np.ones((1, 2, 2))
    node1 = Node(tensor=tensor,
                 name="test_node1",
                 axis_names=["a", "b", "c"],
                 backend=backend)
    node2 = Node(tensor=tensor,
                 name="test_node2",
                 axis_names=["a", "b", "c"],
                 backend=backend)
    tn.connect(node1["b"], node2["b"])
    edge1 = Edge(name="edge", node1=node1, axis1=0)
    edge12 = Edge(name="edge", node1=node1, axis1=1, node2=node2, axis2=1)
    return DoubleNodeEdgeTensor(node1, node2, edge1, edge12, tensor)
Example #24
0
def test_disable_edges_complex(backend):
    a = tn.Node(np.eye(2), backend=backend)
    b = tn.Node(np.eye(2), backend=backend)
    c = tn.Node(np.eye(2), backend=backend)
    e1 = tn.connect(a[0], b[0])
    e2 = tn.connect(b[1], c[0])
    tn.contract(e1)
    tn.contract(e2)
    # This now raises an exception because we contract disables contracted edges
    # and raises a ValueError if we try to access the nodes
    with pytest.raises(ValueError):
        e1.node1
    with pytest.raises(ValueError):
        e2.node1
Example #25
0
def test_contract_name_contracted_node(backend):
    node = tn.Node(np.eye(2), name="Identity Matrix", backend=backend)
    assert node.name == "Identity Matrix"
    edge = tn.connect(node[0], node[1], name="Trace Edge")
    assert edge.name == "Trace Edge"
    final_result = tn.contract(edge, name="Trace Of Identity")
    assert final_result.name == "Trace Of Identity"
def test_node_reorder_edges_raise_error_trace_edge(single_node_edge):
  node = single_node_edge.node
  e2 = tn.connect(node[1], node[2])
  e3 = node[0]
  with pytest.raises(ValueError) as e:
    node.reorder_edges([e2, e3])
  assert "Edge reordering does not support trace edges." in str(e.value)
def test_remove_trace_edge_non_trace_raises_value_error(double_node_edge):
  node1 = double_node_edge.node1
  node2 = double_node_edge.node2
  edge = tn.connect(node1[0], node2[0])
  edge.name = "e"
  with pytest.raises(ValueError, match="Edge 'e' is not a trace edge."):
    _remove_trace_edge(edge, node1)
Example #28
0
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)
Example #29
0
def test_flatten_consistent_tensor(backend):
    a_val = np.ones((2, 3, 4, 5))
    b_val = np.ones((3, 5, 4, 2))
    a = tn.Node(a_val, backend=backend)
    b = tn.Node(b_val, backend=backend)
    e1 = tn.connect(a[0], b[3])
    e2 = tn.connect(b[1], a[3])
    e3 = tn.connect(a[1], b[0])
    tn.flatten_edges([e3, e1, e2])
    tn.check_correct({a, b})

    # Check expected values.
    a_final = np.reshape(np.transpose(a_val, (2, 1, 0, 3)), (4, 30))
    b_final = np.reshape(np.transpose(b_val, (2, 0, 3, 1)), (4, 30))
    np.testing.assert_allclose(a.tensor, a_final)
    np.testing.assert_allclose(b.tensor, b_final)
Example #30
0
def test_edge_disable_complex(backend):
    a = tn.Node(np.eye(2), backend=backend)
    b = tn.Node(np.eye(2), backend=backend)
    c = tn.Node(np.eye(2), backend=backend)
    e1 = tn.connect(a[0], b[0])
    e2 = tn.connect(b[1], c[0])
    tn.contract(e1)
    tn.contract(e2)
    # This now raises an exception because we contract disables contracted edges
    # and raises a ValueError if we try to access the nodes
    with pytest.raises(ValueError):
        e1.node1
    # This raises an exception since the intermediate node created when doing
    # `tn.contract(e2)` was garbage collected.
    with pytest.raises(ValueError):
        e2.node1