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)
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)]
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
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),
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
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])
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))
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'
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))
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