Esempio n. 1
0
def to_quimb_tensor(g: BaseGraph) -> 'qtn.TensorNetwork':
    """Converts tensor network representing the given :func:`pyzx.graph.Graph`.
    Pretty printing: to_tensor(g).draw(color = ['V', 'H'])
    
    Args:
        g: graph to be converted."""

    if qu is None:
        raise ImportError("quimb must be installed to use this function.")

    # copying a graph guarantees consecutive indices, which are needed for the tensor net
    g = g.copy()

    # only Z spiders are handled below
    to_gh(g)

    tensors = []

    # Here we have phase tensors corresponding to Z-spiders with only one output and no input.
    for v in g.vertices():
        if g.type(v) == VertexType.Z and g.phase(v) != 0:
            tensors.append(
                qtn.Tensor(data=[1, np.exp(1j * np.pi * g.phase(v))],
                           inds=(f'{v}', ),
                           tags=("V", )))

    # Hadamard or Kronecker tensors, one for each edge of the diagram.
    for i, edge in enumerate(g.edges()):
        x, y = edge
        isHadamard = g.edge_type(edge) == EdgeType.HADAMARD
        t = qtn.Tensor(data=qu.hadamard()
                       if isHadamard else np.array([1, 0, 0, 1]).reshape(2, 2),
                       inds=(f'{x}', f'{y}'),
                       tags=("H", ) if isHadamard else ("N", ))
        tensors.append(t)

    # TODO: This is not taking care of all the stuff that can be in g.scalar
    # In particular, it doesn't check g.scalar.phasenodes
    # TODO: This will give the wrong tensor when g.scalar.is_zero == True.
    # Grab the float factor and exponent from the scalar
    scalar_float = np.exp(1j * np.pi * g.scalar.phase) * g.scalar.floatfactor
    for node in g.scalar.phasenodes:  # Each node is a Fraction
        scalar_float *= 1 + np.exp(1j * np.pi * node)
    scalar_exp = math.log10(math.sqrt(2)) * g.scalar.power2

    # If the TN is empty, create a single 0-tensor with scalar factor, otherwise
    # multiply the scalar into one of the tensors.
    if len(tensors) == 0:
        tensors.append(qtn.Tensor(data=scalar_float, inds=(), tags=("S", )))
    else:
        tensors[0].modify(data=tensors[0].data * scalar_float)

    network = qtn.TensorNetwork(tensors)

    # the exponent can be very large, so distribute it evenly through the TN
    network.exponent = scalar_exp
    network.distribute_exponent()
    return network
Esempio n. 2
0
    def test_simple(self):
        n = 10
        d_psi = qu.computational_state('0' * n)

        t_psi = Dense1D(d_psi)
        assert set(t_psi.outer_inds()) == {'k{}'.format(i) for i in range(n)}
        assert set(t_psi.tags) == {'I{}'.format(i) for i in range(n)}

        for i in range(n):
            assert t_psi.H @ t_psi.gate(qu.pauli('Z'), i) == pytest.approx(1)

        for i in range(n):
            t_psi.gate_(qu.hadamard(), i)

        assert len(t_psi.tensors) == n + 1

        # should have '++++++++++'
        assert t_psi.H @ t_psi == pytest.approx(1)
        for i in range(n):
            assert t_psi.H @ t_psi.gate(qu.pauli('X'), i) == pytest.approx(1)
Esempio n. 3
0
def apply_U3(psi, theta, phi, lamda, i, **gate_opts):
    mtags = _merge_tags({'U3'}, gate_opts)
    psi.gate_(qu.U_gate(theta, phi, lamda), int(i), tags=mtags, **gate_opts)


def apply_swap(psi, i, j, **gate_opts):
    itag, jtag = map(psi.site_tag, (i, j))
    psi.reindex_({itag: jtag, jtag: itag})


APPLY_GATES = {
    'RX': apply_Rx,
    'RY': apply_Ry,
    'RZ': apply_Rz,
    'U3': apply_U3,
    'H': build_gate_1(qu.hadamard(), tags='H'),
    'X': build_gate_1(qu.pauli('X'), tags='X'),
    'Y': build_gate_1(qu.pauli('Y'), tags='Y'),
    'Z': build_gate_1(qu.pauli('Z'), tags='Z'),
    'S': build_gate_1(qu.S_gate(), tags='S'),
    'T': build_gate_1(qu.T_gate(), tags='T'),
    'X_1_2': build_gate_1(qu.Rx(math.pi / 2), tags='X_1/2'),
    'Y_1_2': build_gate_1(qu.Ry(math.pi / 2), tags='Y_1/2'),
    'Z_1_2': build_gate_1(qu.Rz(math.pi / 2), tags='Z_1/2'),
    'IDEN': lambda *args, **kwargs: None,
    'CX': build_gate_2(qu.cX(), tags='CX'),
    'CY': build_gate_2(qu.cY(), tags='CY'),
    'CZ': build_gate_2(qu.cZ(), tags='CZ'),
    'CNOT': build_gate_2(qu.CNOT(), tags='CNOT'),
    'SWAP': apply_swap,
}