def doSingleShot(q: qreg): init(q) Id(q) MEAS(q) init(q) X(q) MEAS(q)
def initq(a: qreg, b: qreg): with concur: while MEAS(a): X(a) while MEAS(b): X(b)
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 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 SingleShot(qubit: qreg): """ 2-segment sequence with qubit prepared in |0> and |1>, useful for single-shot fidelity measurements and kernel calibration """ init(qubit) Id(qubit) MEAS(qubit) init(qubit) X(qubit) MEAS(qubit)
def main(): x0 = QubitFactory('q1') x1 = QubitFactory('q2') with concur: while not MEAS(x0): X(x0) while not MEAS(x1): X(x1)
def SingleShotNoArg(): """ Sample 0-argument 2-segment sequence with qubit prepared in |0> and |1>, useful for single-shot fidelity measurements and kernel calibration """ qubit = QRegister(1) init(qubit) Id(qubit) MEAS(qubit) init(qubit) X(qubit) MEAS(qubit)
def main(): q1 = QubitFactory("1") q2 = QubitFactory("2") with concur: reset(q1) reset(q2) with concur: X90(q1) X90(q2) with concur: MEAS(q1) MEAS(q2)
def doSPAM(q: qreg, angleSweep, maxSpamBlocks): # Insert an identity at the start of every set to mark them off for angle in angleSweep: init(q) Id(q) MEAS(q) spam_seqs(angle, q, maxSpamBlocks) # Add a final pi for reference init(q) X(q) MEAS(q)
def test_loops(a: qbit, b: qbit): with concur: while True: v1 = MEAS(a) if v1: break X90(a, 1.0, 2.0) X90(a, 1.0, 2.0) while True: v2 = MEAS(b) if v2: break Y90(b)
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 multiQbitTest2(): qs = QRegister('q1', 'q2') Id(qs) X(qs) Barrier(qs) MEAS(qs)
def doRabiWidth(q: qreg, widths): # FIXME: Note the local re-definition of tanh shapeFun = qgl2.basic_sequences.pulses.local_tanh for l in widths: init(q) Utheta(q, length=l, amp=1, phase=0, shapeFun=shapeFun) MEAS(q)
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 doPulsedSpec(q: qreg, specOn): init(q) if specOn: X(q) else: Id(q) MEAS(q)
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 AllXY(q: qreg): # QGL2 version of QGL2 Basic Sequence # Must be compiled & given a QRegister # 6/12/19: Verified this looks same as QGL1 version twentyOnePulsePairs = [ # no pulses to measure |0> (Id, Id), # pulse around same axis (X, X), (Y, Y), # pulse around orthogonal axes (X, Y), (Y, X), # These produce a |+> or |i> state (X90, Id), (Y90, Id), # pulse pairs around orthogonal axes with 1e error sensititivity (X90, Y90), (Y90, X90), # pulse pairs with 2e sensitivity (X90, Y), (Y90, X), (X, Y90), (Y, X90), # pulse pairs around common axis with 3e error sensitivity (X90, X), (X, X90), (Y90, Y), (Y, Y90), # These create the |1> state (X, Id), (Y, Id), (X90, X90), (Y90, Y90) ] # For each of the 21 pulse pairs for (f1, f2) in twentyOnePulsePairs: # Repeat it twice and do a MEAS at the end of each for i in range(2): init(q) f1(q) f2(q) MEAS(q)
def measConcurrently(listNQubits: qreg) -> pulse: '''Concurrently measure given QRegister of qubits. Note: Includes a Barrier on the input qreg to force measurements to be concurrent; QGL1 does Pulse*Pulse == PulseBlock(pulses), which is equivalent.''' qr = QRegister(listNQubits) Barrier(qr) MEAS(qr)
def qreset_full(q: qreg, delay, measSign): m = MEAS(q) Id(q, delay) if m == measSign: X(q) else: Id(q)
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 anotherMulti(): qs = QRegister(2) Id(qs) X(qs) Barrier(qs) MEAS(qs) Y(qs)
def create_seqs(qubit: qbit, fileName): lines = read_ac_lines(fileName) for line in lines: for pulseNum in line: getACPulse(qubit, int(pulseNum)) MEAS(qubit)
def doFlipFlop(qubit: qreg, dragParamSweep, maxNumFFs): # QGL2 qubits are read only, so can't modify qubit.pulse_params[dragScaling], # So no need to save this off and reset afterwards for dragParam in dragParamSweep: # Id sequence for reference init(qubit) Id(qubit) MEAS(qubit) # then a flip flop sequence for a particular DRAG parameter flipflop_seqs(dragParam, maxNumFFs, qubit) # Final pi for reference init(qubit) X(qubit) MEAS(qubit)
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 main(): x = QubitFactory('q1') for i, j in [(1, 2), (3, 4)]: for k in range(j): if MEAS(x): Xtheta(x, i=i, j=j, k=k)
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 runtime_break(): q1 = QRegister("q1") for ct in range(3): m = MEAS(q1) if m: X90(q1) # this should produce an error break
def statetomo(f, q1: qreg, q2: qreg): fncs = [Id, X90, Y90, X] for meas in product(fncs, fncs): init(q1, q2) f(q1, q2) for m, q in zip(meas, (q1, q2)): m(q) for q in (q1, q2): MEAS(q)
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 SPAM(qubit: qreg, angleSweep, maxSpamBlocks=10): """ X-Y sequence (X-Y-X-Y)**n to determine quadrature angles or mixer correction. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) angleSweep : angle shift to sweep over maxSpamBlocks : maximum number of XYXY block to do """ # Original: # def spam_seqs(angle): # """ 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)] # # Insert an identity at the start of every set to mark them off # seqs = list(chain.from_iterable([[[Id(qubit)]] + spam_seqs(angle) for angle in angleSweep])) # # 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, 'SPAM/SPAM') # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) # Insert an identity at the start of every set to mark them off for angle in angleSweep: init(qubit) Id(qubit) MEAS(qubit) spam_seqs(angle, qubit, maxSpamBlocks) # Add a final pi for reference init(qubit) X(qubit) MEAS(qubit)