Example #1
0
def controlled_phase(phi, q, *wires):
    r"""Maps the two-qubit controlled phase gate to the equivalent pyQuil command.

    Args:
        phi (float): the controlled phase angle
        q (int): an integer between 0 and 3 that corresponds to a state
            :math:`\{00, 01, 10, 11\}` on which the conditional phase
            gets applied
        wires (list): list of wires the CPHASE gate acts on

    Returns:
        pyquil.operation: the corresponding pyQuil operation
    """
    # pylint: disable=no-value-for-parameter
    if q == 0:
        return CPHASE00(phi, *wires)
    if q == 1:
        return CPHASE01(phi, *wires)
    if q == 2:
        return CPHASE10(phi, *wires)

    return CPHASE(phi, *wires)
Example #2
0
def _core_qft(qubits, coeff):
    """
    Generates the core program to perform the quantum Fourier transform
    
    :param qubits: A list of qubit indexes.
    :param coeff: A modifier for the angle used in rotations (-1 for inverse 
                  QFT, 1 for QFT)
    :return: A Quil program to compute the core (inverse) QFT of the qubits.
    """

    q = qubits[0]
    qs = qubits[1:]
    if 1 == len(qubits):
        return [H(q)]
    else:
        n = 1 + len(qs)
        cR = []
        for idx, i in enumerate(range(n - 1, 0, -1)):
            q_idx = qs[idx]
            angle = math.pi / 2**(n - i)
            cR.append(CPHASE(coeff * angle)(q, q_idx))
        return _core_qft(qs, coeff) + list(reversed(cR)) + [H(q)]
Example #3
0
def get_test_program(measure: bool = False) -> Program:
    PI = float(pi.evalf())
    p = Program()
    p += X(0)
    p += Y(1)
    p += Z(2)
    p += H(3)
    p += S(0)
    p += T(1)
    p += RX(PI / 2, 2)
    p += RY(PI / 2, 3)
    p += RZ(PI / 2, 0)
    p += CZ(0, 1)
    p += CNOT(2, 3)
    p += CCNOT(0, 1, 2)
    p += CPHASE(PI / 4, 2, 1)
    p += SWAP(0, 3)
    if measure:
        ro = p.declare("ro", "BIT", 4)
        p += MEASURE(0, ro[0])
        p += MEASURE(3, ro[1])
        p += MEASURE(2, ro[2])
        p += MEASURE(1, ro[3])
    return p
Example #4
0
    RY,
    RZ,
    SWAP,
    X,
    QUANTUM_GATES,
)
from pyquil.paulis import PauliTerm, exponentiate, sZ, sX, sI, sY
from pyquil.pyqvm import PyQVM
from pyquil.quil import Program
from pyquil.quilatom import MemoryReference
from pyquil.quilbase import Declare
from pyquil.simulation._reference import ReferenceWavefunctionSimulator

QFT_8_INSTRUCTIONS = [
    H(7),
    CPHASE(1.5707963267948966, 6, 7),
    H(6),
    CPHASE(0.7853981633974483, 5, 7),
    CPHASE(1.5707963267948966, 5, 6),
    H(5),
    CPHASE(0.39269908169872414, 4, 7),
    CPHASE(0.7853981633974483, 4, 6),
    CPHASE(1.5707963267948966, 4, 5),
    H(4),
    CPHASE(0.19634954084936207, 3, 7),
    CPHASE(0.39269908169872414, 3, 6),
    CPHASE(0.7853981633974483, 3, 5),
    CPHASE(1.5707963267948966, 3, 4),
    H(3),
    CPHASE(0.09817477042468103, 2, 7),
    CPHASE(0.19634954084936207, 2, 6),
Example #5
0
 def qft3(q0, q1, q2):
     p = Program()
     p.inst(H(q2), CPHASE(pi / 2.0, q1, q2), H(1), CPHASE(pi / 4.0, q0, q2),
            CPHASE(pi / 2.0, q0, q1), H(q0), SWAP(q0, q2))
     return p
Example #6
0
def test_phases():
    p = Program(PHASE(np.pi, 1), CPHASE00(np.pi, 0, 1), CPHASE01(np.pi, 0, 1),
                CPHASE10(np.pi, 0, 1), CPHASE(np.pi, 0, 1))
    assert p.out() == 'PHASE(pi) 1\nCPHASE00(pi) 0 1\n' \
                      'CPHASE01(pi) 0 1\nCPHASE10(pi) 0 1\n' \
                      'CPHASE(pi) 0 1\n'
for i in range(1, n):
    if sumando_1[i - 1] == "1":
        p += X(a[n - (i + 1)])
for i in range(1, n):
    if sumando_2[i - 1] == "1":
        p += X(b[n - (i + 1)])

# Take the QFT.
# Iterate through the target.
for i in range(n, 0, -1):
    # Apply the Hadamard gate to the target.
    p += H(b[i - 1])

    # Iterate through the control.
    for j in range(i - 1, 0, -1):
        p += CPHASE(2 * pi / 2**(i - j + 1), b[j - 1], b[i - 1])

# Compute controlled-phases.
# Iterate through the targets.
for i in range(n, 0, -1):
    # Iterate through the controls.
    for j in range(i, 0, -1):
        p += CPHASE(2 * pi / 2**(i - j + 1), a[j - 1], b[i - 1])

# Take the inverse QFT.
# Iterate through the target.
for i in range(1, n + 1):
    # Iterate through the control.
    for j in range(1, i):
        # The inverse Fourier transform just uses a negative phase.
        p += CPHASE(-2 * pi / 2**(i - j + 1), b[j - 1], b[i - 1])
Example #8
0
def QFT(q0, q1, q2):
    for i in range(0, len(states)):
        states[i] = states[i] + Program().inst(
            H(q2), CPHASE(pi / 2.0, q1, q2), H(q1), CPHASE(pi / 4.0, q0, q2),
            CPHASE(pi / 2.0, q0, q1), H(q0), SWAP(q0, q2))
Example #9
0
def test_dagger():
    # these gates are their own inverses
    p = Program().inst(I(0), X(0), Y(0), Z(0), H(0), CNOT(0, 1),
                       CCNOT(0, 1, 2), SWAP(0, 1), CSWAP(0, 1, 2))
    assert p.dagger().out() == 'CSWAP 0 1 2\nSWAP 0 1\n' \
                               'CCNOT 0 1 2\nCNOT 0 1\nH 0\n' \
                               'Z 0\nY 0\nX 0\nI 0\n'

    # these gates require negating a parameter
    p = Program().inst(PHASE(pi, 0), RX(pi, 0), RY(pi, 0), RZ(pi, 0),
                       CPHASE(pi, 0, 1), CPHASE00(pi, 0, 1),
                       CPHASE01(pi, 0, 1), CPHASE10(pi, 0, 1), PSWAP(pi, 0, 1))
    assert p.dagger().out() == 'PSWAP(-pi) 0 1\n' \
                               'CPHASE10(-pi) 0 1\n' \
                               'CPHASE01(-pi) 0 1\n' \
                               'CPHASE00(-pi) 0 1\n' \
                               'CPHASE(-pi) 0 1\n' \
                               'RZ(-pi) 0\n' \
                               'RY(-pi) 0\n' \
                               'RX(-pi) 0\n' \
                               'PHASE(-pi) 0\n'

    # these gates are special cases
    p = Program().inst(S(0), T(0), ISWAP(0, 1))
    assert p.dagger().out() == 'PSWAP(pi/2) 0 1\n' \
                               'RZ(pi/4) 0\n' \
                               'PHASE(-pi/2) 0\n'

    # must invert defined gates
    G = np.array([[0, 1], [0 + 1j, 0]])
    p = Program().defgate("G", G).inst(("G", 0))
    assert p.dagger().out() == 'DEFGATE G-INV:\n' \
                               '    0.0, -i\n' \
                               '    1.0, 0.0\n\n' \
                               'G-INV 0\n'

    # can also pass in a list of inverses
    inv_dict = {"G": "J"}
    p = Program().defgate("G", G).inst(("G", 0))
    assert p.dagger(inv_dict=inv_dict).out() == 'J 0\n'

    # defined parameterized gates cannot auto generate daggered version https://github.com/rigetti/pyquil/issues/304
    theta = Parameter('theta')
    gparam_matrix = np.array([[quil_cos(theta / 2), -1j * quil_sin(theta / 2)],
                              [-1j * quil_sin(theta / 2),
                               quil_cos(theta / 2)]])
    g_param_def = DefGate('GPARAM', gparam_matrix, [theta])
    p = Program(g_param_def)
    with pytest.raises(TypeError):
        p.dagger()

    # defined parameterized gates should passback parameters https://github.com/rigetti/pyquil/issues/304
    GPARAM = g_param_def.get_constructor()
    p = Program(GPARAM(pi)(1, 2))
    assert p.dagger().out() == 'GPARAM-INV(pi) 1 2\n'

    # ensure that modifiers are preserved https://github.com/rigetti/pyquil/pull/914
    p = Program()
    control = 0
    target = 1
    cnot_control = 2
    p += X(target).controlled(control)
    p += Y(target).controlled(control)
    p += Z(target).controlled(control)
    p += H(target).controlled(control)
    p += S(target).controlled(control)
    p += T(target).controlled(control)
    p += PHASE(pi, target).controlled(control)
    p += CNOT(cnot_control, target).controlled(control)
    assert p.dagger().out() == 'CONTROLLED CNOT 0 2 1\n' \
                               'CONTROLLED PHASE(-pi) 0 1\n' \
                               'CONTROLLED RZ(pi/4) 0 1\n' \
                               'CONTROLLED PHASE(-pi/2) 0 1\n' \
                               'CONTROLLED H 0 1\n' \
                               'CONTROLLED Z 0 1\n' \
                               'CONTROLLED Y 0 1\n' \
                               'CONTROLLED X 0 1\n'
Example #10
0
x = np.fft.ifft(y, norm='ortho')
print(x)

#==============================================================================
# QFT
#==============================================================================
import math
from pyquil import Program
from pyquil.gates import SWAP, H, CPHASE
from pyquil.api import WavefunctionSimulator

# Initilize program
prog = Program()

# Prepare state
prog = prog.inst(H(0),H(1))
print('Amplitudes a of input state psi: {}'.format(WavefunctionSimulator().wavefunction(prog).amplitudes))

# Perfrom QFT
prog += SWAP(0, 1)
prog += H(1)
prog += CPHASE(math.pi / 2, 0, 1)
prog += H(0)

print('Amplitudes b of output state phi: {}'.format(WavefunctionSimulator().wavefunction(prog).amplitudes))





Example #11
0
def StateInit(qc, circuit_params, p, q, r, s, circuit_choice, control, sign):
    '''This function computes the state produced after the given circuit, either QAOA, IQP, or IQPy,
		depending on the value of circuit_choice.'''

    #sign = 'POSITIVE' for the positive probability version, sign = 'NEGATIVE' for the negative version of the probability (only used to compute the gradients)
    #final_layer is either 'IQP', 'QAOA', 'IQPy' for IQP (Final Hadamard), QAOA (Final X rotation) or IQPy (Final Y rotation)
    #control = 'BIAS' for updating biases, = 'WEIGHTS' for updating weights, = 'NEITHER' for neither

    #Initialise empty quantum program, with QuantumComputer Object, and Wavefunction Simulator
    '''With Active qubit reset'''
    # prog = Program(RESET())
    '''Without Active qubit reset'''
    prog = Program()

    qubits = qc.qubits()
    N_qubits = len(qubits)
    #Unpack circuit parameters from dictionary
    J = circuit_params['J']
    b = circuit_params['b']
    gamma = circuit_params['gamma']
    delta = circuit_params['delta']

    #Apply hadarmard to all qubits in computation
    prog = HadamardToAll(prog, qubits)

    # print(qc.name)

    #Apply Control-Phase(4J) gates to each qubit, the factor of 4 comes from the decomposition of the Ising gate
    #with local Z corrections to neighbouring qubits, coming from the decomposition of the Ising gate
    #If weight J_{p,q} is updated, add a +/- pi/2 rotation
    if qc.name.lower() == 'aspen-3-3q-b-qvm':
        ''''Specific entanglement structure for Rigetti Aspen-3-2Q-C'''
        if (control.lower() == 'weights' and p == 0 and q == 1):
            #first weight parameter between qubit[1] and qubit[2]

            prog.inst(
                CPHASE(4 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0],
                       qubits[1]))
            prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0]))
            prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[1]))

        elif (control.lower() == 'weights' and p == 1 and q == 2):
            #Second weight parameter between qubit[1] and qubit[2]
            prog.inst(
                CPHASE(4 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1],
                       qubits[2]))
            prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1]))
            prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[2]))

        elif (control.lower() == 'neither' or 'bias'
              or 'gamma' and sign.lower() == 'neither'):
            prog.inst(CPHASE(4 * J[0, 1], qubits[0], qubits[1]))
            prog.inst(PHASE(-2 * J[0, 1], qubits[0]))
            prog.inst(PHASE(-2 * J[0, 1], qubits[1]))

            prog.inst(CPHASE(4 * J[1, 2], qubits[1], qubits[2]))
            prog.inst(PHASE(-2 * J[1, 2], qubits[1]))
            prog.inst(PHASE(-2 * J[1, 2], qubits[2]))

    elif qc.name.lower() == 'aspen-4-3q-a' or qc.name.lower(
    ) == 'aspen-4-3q-a-qvm':
        ''''Specific entanglement structure for Rigetti Aspen-4-3Q-A
			17 - 10 - 11
			'''
        if (control.lower() == 'weights' and p == 0 and q == 1):
            #first weight parameter between qubit[1] and qubit[2]

            prog.inst(
                CPHASE(4 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0],
                       qubits[1]))
            prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0]))
            prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[1]))

        elif (control.lower() == 'weights' and p == 1 and q == 2):
            #Second weight parameter between qubit[1] and qubit[2]
            prog.inst(
                CPHASE(4 * J[0, 2] + (-1)**(sign) * pi / 2, qubits[0],
                       qubits[2]))
            prog.inst(PHASE(-2 * J[0, 2] + (-1)**(sign) * pi / 2, qubits[0]))
            prog.inst(PHASE(-2 * J[0, 2] + (-1)**(sign) * pi / 2, qubits[2]))

        elif (control.lower() == 'neither' or 'bias'
              or 'gamma' and sign.lower() == 'neither'):
            prog.inst(CPHASE(4 * J[0, 1], qubits[0], qubits[1]))
            prog.inst(PHASE(-2 * J[0, 1], qubits[0]))
            prog.inst(PHASE(-2 * J[0, 1], qubits[1]))

            prog.inst(CPHASE(4 * J[0, 2], qubits[0], qubits[2]))
            prog.inst(PHASE(-2 * J[0, 2], qubits[0]))
            prog.inst(PHASE(-2 * J[0, 2], qubits[2]))

    elif qc.name.lower() == 'aspen-4-4q-a' or qc.name.lower(
    ) == 'aspen-4-4q-a-qvm':
        ''''
			Specific entanglement structure for Rigetti Aspen-4-4Q-A 
			7 - 0 - 1 - 2
			'''
        if (control.lower() == 'weights' and p == 0 and q == 1):
            #first weight parameter between qubit[1] and qubit[2]

            prog.inst(
                CPHASE(4 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0],
                       qubits[1]))
            prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[0]))
            prog.inst(PHASE(-2 * J[0, 1] + (-1)**(sign) * pi / 2, qubits[1]))

        elif (control.lower() == 'weights' and p == 1 and q == 2):
            #Second weight parameter between qubit[1] and qubit[2]
            prog.inst(
                CPHASE(4 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1],
                       qubits[2]))
            prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[1]))
            prog.inst(PHASE(-2 * J[1, 2] + (-1)**(sign) * pi / 2, qubits[2]))

        elif (control.lower() == 'weights' and p == 0 and q == 3):
            #Second weight parameter between qubit[1] and qubit[2]
            prog.inst(
                CPHASE(4 * J[0, 3] + (-1)**(sign) * pi / 2, qubits[0],
                       qubits[3]))
            prog.inst(PHASE(-2 * J[0, 3] + (-1)**(sign) * pi / 2, qubits[0]))
            prog.inst(PHASE(-2 * J[0, 3] + (-1)**(sign) * pi / 2, qubits[3]))

        elif (control.lower() == 'neither' or 'bias'
              or 'gamma' and sign.lower() == 'neither'):
            prog.inst(CPHASE(4 * J[0, 1], qubits[0], qubits[1]))
            prog.inst(PHASE(-2 * J[0, 1], qubits[0]))
            prog.inst(PHASE(-2 * J[0, 1], qubits[1]))

            prog.inst(CPHASE(4 * J[1, 2], qubits[1], qubits[2]))
            prog.inst(PHASE(-2 * J[1, 2], qubits[1]))
            prog.inst(PHASE(-2 * J[1, 2], qubits[2]))

            prog.inst(CPHASE(4 * J[0, 3], qubits[0], qubits[3]))
            prog.inst(PHASE(-2 * J[0, 3], qubits[0]))
            prog.inst(PHASE(-2 * J[0, 3], qubits[3]))
    else:
        for j in range(0, N_qubits):
            for i in range(0, N_qubits):
                if (
                        i < j
                ):  #connection is symmetric, so don't overcount entangling gates
                    if (control.lower() == 'weights' and i == p and j == q):
                        prog.inst(
                            CPHASE(4 * J[i, j] + (-1)**(sign) * pi / 2,
                                   qubits[i], qubits[j]))
                        prog.inst(
                            PHASE(-2 * J[i, j] + (-1)**(sign) * pi / 2,
                                  qubits[i]))
                        prog.inst(
                            PHASE(-2 * J[i, j] + (-1)**(sign) * pi / 2,
                                  qubits[j]))

                    elif (control.lower() == 'neither' or 'bias'
                          or 'gamma' and sign.lower() == 'neither'):
                        prog.inst(CPHASE(4 * J[i, j], qubits[i], qubits[j]))
                        prog.inst(PHASE(-2 * J[i, j], qubits[i]))
                        prog.inst(PHASE(-2 * J[i, j], qubits[j]))

    #Apply local Z rotations (b) to each qubit (with one phase changed by pi/2 if the corresponding parameter {r} is being updated
    for j in range(0, N_qubits):
        if (control == 'BIAS' and j == r):
            prog.inst(PHASE(-2 * b[j] + (-1)**(sign) * pi / 2, qubits[j]))
        elif (control == 'NEITHER' or 'WEIGHTS'
              or 'GAMMA' and sign == 'NEITHER'):
            prog.inst(PHASE(-2 * b[j], qubits[j]))

    #Apply final 'measurement' layer to all qubits, either all Hadamard, or X or Y rotations
    if (circuit_choice == 'IQP'):
        prog = HadamardToAll(
            prog, qubits
        )  #If the final 'measurement' layer is to be an IQP measurement (i.e. Hadamard on all qubits)

    elif (circuit_choice == 'QAOA'):
        #If the final 'measurement' layer is to be a QAOA measurement (i.e. e^(-i(pi/4)X_i)on all qubits)
        for k in range(0, N_qubits):
            # if (control == 'GAMMA' and k == s):
            # 	prog.inst(pl.exponential_map(sX(k))(-float(gamma[k])+ (-1)**(sign)*pi/2))

            # elif (control == 'NEITHER' or 'WEIGHTS' or 'BIAS' and sign == 'NEITHER'):
            H_temp = (-float(gamma[k])) * pl.sX(qubits[k])
            prog.inst(pl.exponential_map(H_temp)(1.0))
            # print('GAMMA IS:',-float(gamma[k]))
    elif (circuit_choice == 'IQPy'):
        #If the final 'measurement' layer is to be a IQPy measurement (i.e. e^(-i(pi/4)Y_i) on all qubits)
        for k in qubits:
            H_temp = (-float(delta[k])) * pl.sY(qubits[k])
            prog.inst(pl.exponential_map(H_temp)(1.0))

    else:
        raise ValueError("circuit_choice must be either  \
							\'IQP\' for IQP (Final Hadamard), \
							\'QAOA\' for QAOA (Final X rotation) or \
							\'IQPy\' IQPy (Final Y rotation)")
    # print(prog)
    '''Insert explicit measure instruction if required'''
    # ro = prog.declare('ro', 'BIT', len(qubits))
    # prog.inst([MEASURE(qubit, ro[idx]) for idx, qubit in enumerate(qubits)])

    return prog