def qaoa_ansatz(betas, gammas, h_cost, h_driver):
    pq = Program()
    pq += [
        exponentiate_commuting_pauli_sum(h_cost)(g) +
        exponentiate_commuting_pauli_sum(h_driver)(b)
        for g, b in zip(gammas, betas)
    ]
    return pq
Пример #2
0
def qaoa_ansatz(gammas, betas):
    """
    Function that returns a QAOA ansatz program for a list of angles betas and gammas. len(betas) ==
    len(gammas) == P for a QAOA program of order P.
    :param list(float) gammas: Angles over which to parameterize the cost Hamiltonian.
    :param list(float) betas: Angles over which to parameterize the driver Hamiltonian.
    :return: The QAOA ansatz program.
    :rtype: Program.
    """
    return Program([exponentiate_commuting_pauli_sum(h_cost)(g) + exponentiate_commuting_pauli_sum(h_driver)(b) \
        for g, b in zip(gammas, betas)])
Пример #3
0
def qaoa_ansatz(gammas, betas):
    """
    각도 betas와 gammas의 배열로 주어지는 QAOA 가정법(ansatz) 프로그램을 반환하는 함수.
    차수(order) P인 QAOA program은 len(betas) == len(gammas) == P를 갖는다.
    :param list(float) gammas: 비용 해밀토니안을 매개변수화하는 각도값들의 배열.
    :param list(float) betas: 구동 해밀토니안을 매개변수화하는 각도값들의 배열.
    :return: QAOA 가정법 프로그램.
    :rtype: 프로그램.
    """
    return Program([
        exponentiate_commuting_pauli_sum(h_cost)(g) +
        exponentiate_commuting_pauli_sum(h_driver)(b)
        for g, b in zip(gammas, betas)
    ])
def test_exponentiate_commuting_pauli_sum():
    q = QubitPlaceholder.register(8)
    pauli_sum = PauliSum(
        [PauliTerm('Z', q[0], 0.5),
         PauliTerm('Z', q[1], 0.5)])
    prog = Program().inst(RZ(1., q[0])).inst(RZ(1., q[1]))
    result_prog = exponentiate_commuting_pauli_sum(pauli_sum)(1.)
    assert address_qubits(prog) == address_qubits(result_prog)
Пример #5
0
def uccsd_ansatz_circuit(packed_amplitudes, n_orbitals, n_electrons, cq=None):
    # TODO apply logical re-ordering to Fermionic non-parametric way too!
    """
    This function returns a UCCSD variational ansatz with hard-coded gate angles. The number of orbitals specifies the
    number of qubits, the number of electrons specifies the initial HF reference state which is assumed was prepared.
    The packed_amplitudes input defines which gate angles to apply for each CC operation. The list cq is an optional
    list which specifies the qubit label ordering which is to be assumed.

    :param list() packed_amplitudes: amplitudes t_ij and t_ijkl of the T_1 and T_2 operators of the UCCSD ansatz
    :param int n_orbitals: number of *spatial* orbitals
    :param int n_electrons: number of electrons considered
    :param list() cq: list of qubit label order

    :return: circuit which prepares the UCCSD variational ansatz
    :rtype: Program
    """

    # Fermionic UCCSD
    uccsd_propagator = normal_ordered(
        uccsd_singlet_generator(packed_amplitudes, 2 * n_orbitals,
                                n_electrons))
    qubit_operator = jordan_wigner(uccsd_propagator)

    # convert the fermionic propagator to a Pauli spin basis via JW, then convert to a Pyquil compatible PauliSum
    pyquilpauli = qubitop_to_pyquilpauli(qubit_operator)

    # re-order logical stuff if necessary
    if cq is not None:
        pauli_list = [PauliTerm("I", 0, 0.0)]
        for term in pyquilpauli.terms:
            new_term = term
            # if the QPU has a custom lattice labeling, supplied by user through a list cq, reorder the Pauli labels.
            if cq is not None:
                new_term = term.coefficient
                for pauli in term:
                    new_index = cq[pauli[0]]
                    op = pauli[1]
                    new_term = new_term * PauliTerm(op=op, index=new_index)

            pauli_list.append(new_term)
        pyquilpauli = PauliSum(pauli_list)

    # create a pyquil program which performs the ansatz state preparation with angles unpacked from packed_amplitudes
    ansatz_prog = Program()

    # add each term as successive exponentials (1 single Trotter step, not taking into account commutation relations!)
    for commuting_set in commuting_sets(simplify_pauli_sum(pyquilpauli)):
        ansatz_prog += exponentiate_commuting_pauli_sum(
            -1j * PauliSum(commuting_set))(-1.0)

    return ansatz_prog
Пример #6
0
def estimateZ(A, B, N, t):
    absA = LA.norm(np.asarray(A), 1)
    absB = LA.norm(np.asarray(B), 1)

    A = 0.5 * (absA + absB)
    B = 0.5 * (absA - absB)
    I = PauliTerm("I", 0, coefficient=A)
    Z = PauliTerm("Z", 0, coefficient=B)
    H = (I + Z) * PauliTerm("X", 1)
    exponential = exponentiate_commuting_pauli_sum(H)

    value = 0
    for i in range(N):
        phi = Program(X(0), H(0))
        ro = phi.declare('ro', 'BIT', 1)
        phi += exponential(t)
        phi += MEASURE(1, ro[0])

        if (wf_sim.wavefunction(phi).amplitudes[0] == 0):
            value += 1
    return math.sqrt(2 * (value / N)) / (t)
Пример #7
0
def test_exponentiate_commuting_pauli_sum():
    pauli_sum = PauliSum([PauliTerm('Z', 0, 0.5), PauliTerm('Z', 1, 0.5)])
    prog = Program().inst(RZ(1., 0)).inst(RZ(1., 1))
    result_prog = exponentiate_commuting_pauli_sum(pauli_sum)(1.)
    assert prog == result_prog
Пример #8
0
def dotProduct(A, B):
    """
    calculate dot product between two boolean vectors of same length 
    """
    absA = LA.norm(np.asarray(A), 1)
    absB = LA.norm(np.asarray(B), 1)

    a = 0.5 * (absA + absB)
    b = 0.5 * (absA - absB)
    I = PauliTerm("I", 0, coefficient=a)
    Z = PauliTerm("Z", 0, coefficient=b)
    Hamil = (I + Z) * PauliTerm("X", 1)
    exponential = exponentiate_commuting_pauli_sum(Hamil)

    zeros = 0
    ones = 0
    while (True):
        #print('while..')
        phi = Program()
        phi.inst(X(0))
        phi.inst(H(0))
        phi.inst(exponential(0.1))
        ro = phi.declare('ro', 'BIT', 1)
        phi += MEASURE(1, ro[0])
        if (wf_sim.wavefunction(phi).amplitudes[0] == 0):
            psi = Program(H(1))
            for index in range(len(B)):
                if B[index] == 1:
                    psi = psi + CNOT(1, index + 2)
            psi = psi + X(1)
            for index in range(len(A)):
                if A[index] == 1:
                    psi = psi + CNOT(1, index + 2)
            psi = psi + X(0)

            ancilla = Program(H(2 + len(A)))
            for index in range((len(B))):
                ancilla += CSWAP(2 + len(A), index, index + 1)
            ancilla += H(2 + len(A))

            swaptest = phi + psi + ancilla

            ro2 = swaptest.declare('ro2', 'BIT', 1)
            swaptest += MEASURE(2 + len(A), ro2[0])
            for i in range(2**(3 + len(A))):
                if (wf_sim.wavefunction(swaptest).amplitudes[i] != 0):
                    if (i < (2**(2 + len(A)))):
                        zeros += 1
                    else:
                        ones += 1
                    break
            print('measure success')
            print('zeros+ones = ', zeros + ones)
            if (zeros + ones > 1000):
                print('zeors and ondes are', zeros, ones)
                return (zeros - ones) / (zeros + ones)
                break
            else:
                continue
        else:
            continue
Пример #9
0
from pyquil.paulis import ID, sX, sY, sZ
from pyquil import *
from pyquil.gates import H

import pyquil.paulis as pl

# Pauli term takes an operator "X", "Y", "Z", or "I"; a qubit to act on, and
# an optional coefficient.
a = 1 * ID()
b = -0.75 * sX(0) * sY(1) * sZ(3)
c = (5-2j) * sZ(1) * sX(2)

# Construct a sum of Pauli terms.
sigma = a + b + c
print("sigma = {}".format(sigma))
p = Program()
p.inst(pl.exponentiate_commuting_pauli_sum(sigma))

print(p)