def t2(): """ Expected: [X(q1), X(q1), X(q1), X(q1)] """ q1 = QRegister('q1') l1 = [0, 1, 2, 3] l1 = l1[:2] + l1[2:] if l1 == [0, 1, 2, 3]: X(q1) else: Y(q1) l1 = l1[2:] + l1[:2] if l1 == [2, 3, 0, 1]: X(q1) else: Y(q1) l1 = l1[3:] + l1[:3] if l1 == [1, 2, 3, 0]: X(q1) else: Y(q1) l1 = l1[1:] + l1[:1] if l1 == [2, 3, 0, 1]: X(q1) else: Y(q1)
def t3(): """ Expected: [X(q1), X(q1), X(q1)] """ q1 = QRegister('q1') total = 0 if total == 0: X(q1) else: Y(q1) total += 2 if total == 2: total += 2 X(q1) else: total += 1 Y(q1) if total == 4: X(q1) else: Y(q1)
def doRabiAmpPi(qr: qreg, amps): for l in amps: init(qr) X(qr[1]) Utheta(qr[0], amp=l, phase=0) X(qr[1]) MEAS(qr[1])
def initq(a: qreg, b: qreg): with concur: while MEAS(a): X(a) while MEAS(b): X(b)
def t1(): """ Correct result is [ X(q1), X(q1), X(q1) ] """ q1 = QRegister('q1') (x, y, z) = (1, 2, 3) if (x, y, z) == (1, 2, 3): X(q1) else: print('oops 1') Y(q1) (x, y, z) = (y, z, x) if (x, y, z) == (2, 3, 1): X(q1) else: print('oops 2') Y(q1) (x, y, z) = (y, z, x) if (x, y, z) == (3, 1, 2): X(q1) else: print('oops 3') Y(q1)
def CRtomo_seq(controlQ: qreg, targetQ: qreg, lengths, ph, amp=0.8, riseFall=20e-9): """ Variable length CX experiment, for Hamiltonian tomography. Parameters ---------- controlQ : logical channel for the control qubit (LogicalChannel) targetQ: logical channel for the target qubit (LogicalChannel) lengths : pulse lengths of the CR pulse to sweep over (iterable) riseFall : rise/fall time of the CR pulse (s) ph : phase of the CR pulse (rad) """ # Rather than do EdgeFactory and regular flat_top_gaussian, # define a new QGL2 stub where the QGL1 implementation does that, # so QGL2 can avoid dealing with the edge # CRchan = EdgeFactory(controlQ, targetQ) # flat_top_gaussian is an addition of 3 UTheta pulses cNt = QRegister(controlQ, targetQ) tomo_pulses = [Y90m, X90, Id] # Sequence 1 for l, tomo_pulse in product(lengths, tomo_pulses): init(cNt) Id(controlQ) flat_top_gaussian_edge(controlQ, targetQ, riseFall=riseFall, length=l, amp=amp, phase=ph, label="CR") Barrier(cNt) Id(controlQ) tomo_pulse(targetQ) MEAS(targetQ) # Sequence 2 for l, tomo_pulse in product(lengths, tomo_pulses): init(cNt) X(controlQ) flat_top_gaussian_edge(controlQ, targetQ, riseFall=riseFall, length=l, amp=amp, phase=ph, label="CR") Barrier(cNt) X(controlQ) tomo_pulse(targetQ) MEAS(targetQ) create_cal_seqs(targetQ, 2)
def PiRabi(controlQ: qreg, targetQ: qreg, lengths, riseFall=40e-9, amp=1, phase=0, calRepeats=2): """ Variable length CX experiment. Parameters ---------- controlQ : logical channel for the control qubit (LogicalChannel) targetQ: logical channel for the target qubit (LogicalChannel) lengths : pulse lengths of the CR pulse to sweep over (iterable) riseFall : rise/fall time of the CR pulse (s) amp : amplitude of the CR pulse phase : phase of the CR pulse (rad) calRepeats : number repetitions of calibration sequences (int) """ # Rather than do EdgeFactory and regular flat_top_gaussian, # define a new QGL2 stub where the QGL1 implementation does that, # so QGL2 can avoid dealing with the edge # CRchan = EdgeFactory(controlQ, targetQ) # flat_top_gaussian is an addition of 3 UTheta pulses cNt = QRegister(controlQ, targetQ) # Sequence 1: Id(control), gaussian(l), measure both for l in lengths: init(cNt) Id(controlQ) flat_top_gaussian_edge(controlQ, targetQ, riseFall, length=l, amp=amp, phase=phase) measConcurrently(cNt) # Sequence 2: X(control), gaussian(l), X(control), measure both for l in lengths: init(cNt) X(controlQ) flat_top_gaussian_edge(controlQ, targetQ, riseFall, length=l, amp=amp, phase=phase) X(controlQ) measConcurrently(cNt) # Then do calRepeats calibration sequences create_cal_seqs(cNt, calRepeats)
def edgeTest3(): q1 = QRegister('q1') q2 = QRegister('q2') for q in [q1, q2]: init(q) echoCR(q1, q2) X(q2) Y(q2) Id(q2) X(q2)
def main(): x0 = QubitFactory('q1') x1 = QubitFactory('q2') with concur: while not MEAS(x0): X(x0) while not MEAS(x1): X(x1)
def spam_seqs(angle, q: qreg, maxSpamBlocks=10): for rep in range(maxSpamBlocks): init(q) Y90(q) for _ in range(rep): X(q) U(q, phase=pi / 2 + angle) X(q) U(q, phase=pi / 2 + angle) X90(q) MEAS(q)
def EchoCRAmp(controlQ: qreg, targetQ: qreg, amps, riseFall=40e-9, length=50e-9, phase=0, calRepeats=2): """ Variable amplitude CX experiment, with echo pulse sandwiched between two CR opposite-phase pulses. Parameters ---------- controlQ : logical channel for the control qubit (LogicalChannel) targetQ: logical channel for the target qubit (LogicalChannel) amps : pulse amplitudes of the CR pulse to sweep over (iterable) riseFall : rise/fall time of the CR pulse (s) length : duration of each of the two flat parts of the CR pulse (s) phase : phase of the CR pulse (rad) calRepeats : number of repetitions of readout calibrations for each 2-qubit state """ cNt = QRegister(controlQ, targetQ) # Sequence 1 for a in amps: init(cNt) Id(controlQ) echoCR(controlQ, targetQ, length=length, phase=phase, riseFall=riseFall, amp=a) Id(controlQ) measConcurrently(cNt) # Sequence 2 for a in amps: init(cNt) X(controlQ) echoCR(controlQ, targetQ, length=length, phase=phase, riseFall=riseFall, amp=a) X(controlQ) measConcurrently(cNt) # Then do calRepeats calibration sequences create_cal_seqs(cNt, calRepeats)
def spam_seqs(angle, qubit: qreg, maxSpamBlocks=10): """ Helper function to create a list of sequences increasing SPAM blocks with a given angle. """ #SPAMBlock = [X(qubit), U(qubit, phase=pi/2+angle), X(qubit), U(qubit, phase=pi/2+angle)] #return [[Y90(qubit)] + SPAMBlock*rep + [X90(qubit)] for rep in range(maxSpamBlocks)] for rep in range(maxSpamBlocks): init(qubit) Y90(qubit) for _ in range(rep): X(qubit) U(qubit, phase=pi / 2 + angle) X(qubit) U(qubit, phase=pi / 2 + angle) X90(qubit) MEAS(qubit)
def foo(q1: qreg, q2: qreg): with concur: while True: m1 = MEAS(q1) if m1: break else: X(q1) while True: m2 = MEAS(q2) if m2: break else: X(q2)
def qreset_with_delay(q: qreg, delay): m = MEAS(q) # Wait to make branching time deterministic, and to allow residual # measurement photons to decay Id(q, delay) if m == 1: X(q)
def doPulsedSpec(q: qreg, specOn): init(q) if specOn: X(q) else: Id(q) MEAS(q)
def qreset_full(q: qreg, delay, measSign): m = MEAS(q) Id(q, delay) if m == measSign: X(q) else: Id(q)
def doSingleShot(q: qreg): init(q) Id(q) MEAS(q) init(q) X(q) MEAS(q)
def anotherMulti(): qs = QRegister(2) Id(qs) X(qs) Barrier(qs) MEAS(qs) Y(qs)
def InversionRecovery(qubit: qreg, delays, calRepeats=2): """ Inversion recovery experiment to measure qubit T1 Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) delays : delays after inversion before measurement (iterable; seconds) calRepeats : how many repetitions of calibration pulses (int) """ # Original: # # Create the basic sequences # seqs = [[X(qubit), Id(qubit, d), MEAS(qubit)] for d in delays] # # Tack on the calibration scalings # seqs += create_cal_seqs((qubit,), calRepeats) # fileNames = compile_to_hardware(seqs, 'T1'+('_'+qubit.label)*suffix+'/T1'+('_'+qubit.label)*suffix) # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) for d in delays: init(qubit) X(qubit) Id(qubit, length=d) MEAS(qubit) # Tack on calibration create_cal_seqs(qubit, calRepeats)
def multiQbitTest2(): qs = QRegister('q1', 'q2') Id(qs) X(qs) Barrier(qs) MEAS(qs)
def bar(): q1 = QubitFactory("1") q2 = QubitFactory("2") with concur: while True: m1 = MEAS(q1) if m1: break else: X(q1) while True: m2 = MEAS(q2) if m2: break else: X(q2)
def EchoCRPhase(controlQ: qreg, targetQ: qreg, phases, riseFall=40e-9, amp=1, length=100e-9, calRepeats=2, canc_amp=0, canc_phase=np.pi/2): """ Variable phase CX experiment, with echo pulse sandwiched between two CR opposite-phase pulses. Parameters ---------- controlQ : logical channel for the control qubit (LogicalChannel) targetQ : logical channel for the cross-resonance pulse (LogicalChannel) phases : pulse phases of the CR pulse to sweep over (iterable) riseFall : rise/fall time of the CR pulse (s) amp : amplitude of the CR pulse length : duration of each of the two flat parts of the CR pulse (s) calRepeats : number of repetitions of readout calibrations for each 2-qubit state """ # Original: # seqs = [[Id(controlQ)] + echoCR(controlQ, targetQ, length=length, phase=ph, riseFall=riseFall) + [X90(targetQ)*Id(controlQ), MEAS(targetQ)*MEAS(controlQ)] \ # for ph in phases]+[[X(controlQ)] + echoCR(controlQ, targetQ, length=length, phase= ph, riseFall = riseFall) + [X90(targetQ)*X(controlQ), MEAS(targetQ)*MEAS(controlQ)] \ # for ph in phases]+create_cal_seqs((targetQ,controlQ), calRepeats, measChans=(targetQ,controlQ)) cNt = QRegister(controlQ, targetQ) # Sequence 1 for ph in phases: init(cNt) Id(controlQ) echoCR(controlQ, targetQ, length=length, phase=ph, riseFall=riseFall, canc_amp=canc_amp, canc_phase=canc_phase) Barrier(cNt) X90(targetQ) Id(controlQ) measConcurrently(cNt) # Sequence 2 for ph in phases: init(cNt) X(controlQ) echoCR(controlQ, targetQ, length=length, phase=ph, riseFall=riseFall, canc_amp=canc_amp, canc_phase=canc_phase) Barrier(cNt) X90(targetQ) X(controlQ) measConcurrently(cNt) # Then do calRepeats calibration sequences create_cal_seqs(cNt, calRepeats)
def doInversionRecovery(q:qreg, delays, calRepeats): for d in delays: init(q) X(q) Id(q, length=d) MEAS(q) # Tack on calibration create_cal_seqs(q, calRepeats)
def doSwap(qr: qreg, delays): for d in delays: init(qr) X(qr) Id(qr[1], length=d) Barrier(qr) MEAS(qr) create_cal_seqs(qr, 2)
def FlipFlop(qubit: qreg, dragParamSweep, maxNumFFs=10): """ Flip-flop sequence (X90-X90m)**n to determine off-resonance or DRAG parameter optimization. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) dragParamSweep : drag parameter values to sweep over (iterable) maxNumFFs : maximum number of flip-flop pairs to do """ # Original: # def flipflop_seqs(dragScaling): # """ Helper function to create a list of sequences with a specified drag parameter. """ # qubit.pulse_params['dragScaling'] = dragScaling # return [[X90(qubit)] + [X90(qubit), X90m(qubit)]*rep + [Y90(qubit)] for rep in range(maxNumFFs)] # # Insert an identity at the start of every set to mark them off # originalScaling = qubit.pulse_params['dragScaling'] # seqs = list(chain.from_iterable([[[Id(qubit)]] + flipflop_seqs(dragParam) for dragParam in dragParamSweep])) # qubit.pulse_params['dragScaling'] = originalScaling # # Add a final pi for reference # seqs.append([X(qubit)]) # # Add the measurment block to every sequence # measBlock = MEAS(qubit) # for seq in seqs: # seq.append(measBlock) # fileNames = compile_to_hardware(seqs, 'FlipFlop/FlipFlop') # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) # Insert an identity at the start of every set to mark them off # Want a result something like: # [['Id'], ['X9', 'Y9'], ['X9', 'X9', 'X9m', 'Y9'], ['X9', 'X9', 'X9m', 'X9', 'X9m', 'Y9'], ['Id'], ['X9', 'Y9'], ['X9', 'X9', 'X9m', 'Y9'], ['X9', 'X9', 'X9m', 'X9', 'X9m', 'Y9'], ['Id'], ['X9', 'Y9'], ['X9', 'X9', 'X9m', 'Y9'], ['X9', 'X9', 'X9m', 'X9', 'X9m', 'Y9']] # QGL2 qubits are read only, so can't modify qubit.pulse_params[dragScaling], # Instead of modifying qubit, we'll just supply the drag param explicitly to each pulse # So no need to save this off and reset afterwards # originalScaling = qubit.pulse_params['dragScaling'] for dragParam in dragParamSweep: init(qubit) Id(qubit) MEAS(qubit) flipflop_seqs(dragParam, maxNumFFs, qubit) # qubit.pulse_params['dragScaling'] = originalScaling # Add a final pi for reference init(qubit) X(qubit) MEAS(qubit)
def main(): x = QubitFactory('1') y = QubitFactory('2') z = QubitFactory('3') for q in [x, y, z]: with concur: X(q) Y(q)
def anotherMulti2(): qs = QRegister(3) qsub = QRegister(qs[0], qs[1]) Id(qsub) X(qs[0:2]) # equivalent to calling with qsub argument Barrier(qs) MEAS(qsub) Barrier(qs) Y(qs[0]) Y(qs[2])
def PulsedSpec(qubit: qreg, specOn=True): """ Measurement preceded by a X pulse if specOn """ init(qubit) if specOn: X(qubit) else: Id(qubit) MEAS(qubit)
def classical_continue(): q1 = QRegister("q1") for ct in range(3): X(q1) if ct >= 1: X90(q1) continue X90(q1) Y90(q1)
def classical_break(): q1 = QRegister("q1") for ct in range(3): X(q1) if ct >= 1: X90(q1) break X90(q1) Y90(q1)