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 RabiAmp_NQubits(qubits: qreg, amps, phase=0, measChans: qreg = None, docals=False, calRepeats=2): """ Variable amplitude Rabi nutation experiment for an arbitrary number of qubits simultaneously Parameters ---------- qubits : tuple of logical channels to implement sequence (LogicalChannel) amps : pulse amplitudes to sweep over for all qubits (iterable) phase : phase of the pulses (radians) measChans : tuple of qubits to be measured (use qubits if not specified) (LogicalChannel) docals, calRepeats: enable calibration sequences, repeated calRepeats times """ if measChans is None: measChans = qubits allChans = QRegister(qubits, measChans) for amp in amps: init(allChans) Utheta(qubits, amp=amp, phase=phase) measConcurrently(measChans) if docals: create_cal_seqs(qubits, calRepeats, measChans)
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 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 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 doRabiAmp_NQubits(qr: qreg, amps, docals, calRepeats): p = 0 for a in amps: init(qr) Utheta(qr, amp=a, phase=p) MEAS(qr) if docals: create_cal_seqs(qr, calRepeats)
def SimultaneousRB_AC(qubits: qreg, seqs, add_cals=True): """ Simultaneous randomized benchmarking on multiple qubits using atomic Clifford pulses. Parameters ---------- qubits : QRegister of logical channels to implement seqs on seqs : a tuple of sequences created for each qubit in qubits Example ------- >>> q1 = QubitFactory('q1') >>> q2 = QubitFactory('q2') >>> seqs1 = create_RB_seqs(1, [2, 4, 8, 16]) >>> seqs2 = create_RB_seqs(1, [2, 4, 8, 16]) >>> qr = QRegister(q1, q2) >>> SimultaneousRB_AC(qr, (seqs1, seqs2)) """ # Original: # seqsBis = [] # for seq in zip(*seqs): # seqsBis.append([reduce(operator.__mul__, [AC(q,c) for q,c in zip(qubits, # pulseNums)]) for pulseNums in zip(*seq)]) # # Add the measurement to all sequences # for seq in seqsBis: # seq.append(reduce(operator.mul, [MEAS(q) for q in qubits])) # axis_descriptor = [{ # 'name': 'length', # 'unit': None, # 'points': list(map(len, seqs)), # 'partition': 1 # }] # # Tack on the calibration sequences # if add_cals: # seqsBis += create_cal_seqs((qubits), 2) # axis_descriptor.append(cal_descriptor((qubits), 2)) # metafile = compile_to_hardware(seqsBis, 'RB/RB', axis_descriptor = axis_descriptor, extra_meta = {'sequences':seqs}) for seq in zip(*seqs): # Start sequence init(qubits) for pulseNums in zip(*seq): Barrier(qubits) for q, c in zip(qubits, pulseNums): AC(q, c) # Measure at end of each sequence measConcurrently(qubits) if add_cals: # Tack on calibration create_cal_seqs(qubits, 2)
def SingleQubitRB_AC(qubit: qreg, seqs, purity=False, add_cals=True): """ Single qubit randomized benchmarking using atomic Clifford pulses. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) seqFile : file containing sequence strings """ # Original: # seqsBis = [] # op = [Id(qubit, length=0), Y90m(qubit), X90(qubit)] # for ct in range(3 if purity else 1): # for seq in seqs: # seqsBis.append([AC(qubit, c) for c in seq]) # #append tomography pulse to measure purity # seqsBis[-1].append(op[ct]) # #append measurement # seqsBis[-1].append(MEAS(qubit)) # # Tack on the calibration sequences # if add_cals: # seqsBis += create_cal_seqs((qubit,), 2) # axis_descriptor = [{ # 'name': 'length', # 'unit': None, # 'points': list(map(len, seqs)), # 'partition': 1 # }] # metafile = compile_to_hardware(seqsBis, 'RB/RB', axis_descriptor = axis_descriptor, extra_meta = {'sequences':seqs}) # AC() gives a single pulse on qubit op = [Id, Y90m, X90] for ct in range(3 if purity else 1): for seq in seqs: init(qubit) for c in seq: AC(qubit, c) # append tomography pulse to measure purity # See issue #: 53 func = op[ct] if ct == 0: func(qubit, length=0) else: func(qubit) # append measurement MEAS(qubit) if add_cals: # Tack on calibration sequences create_cal_seqs(qubit, 2)
def SimultaneousRB_AC(qubits: qreg, seqs, showPlot=False): """ Simultaneous randomized benchmarking on multiple qubits using atomic Clifford pulses. Parameters ---------- qubits : iterable of logical channels to implement seqs on (list or tuple) seqs : a tuple of sequences created for each qubit in qubits showPlot : whether to plot (boolean) Example ------- >>> q1 = QubitFactory('q1') >>> q2 = QubitFactory('q2') >>> seqs1 = create_RB_seqs(1, [2, 4, 8, 16]) >>> seqs2 = create_RB_seqs(1, [2, 4, 8, 16]) >>> SimultaneousRB_AC((q1, q2), (seqs1, seqs2), showPlot=False) """ # Original: # seqsBis = [] # for seq in zip(*seqs): # seqsBis.append([reduce(operator.__mul__, [AC(q,c) for q,c in zip(qubits, # pulseNums)]) for pulseNums in zip(*seq)]) # # Add the measurement to all sequences # for seq in seqsBis: # seq.append(reduce(operator.mul, [MEAS(q) for q in qubits])) # # Tack on the calibration sequences # seqsBis += create_cal_seqs((qubits), 2) # fileNames = compile_to_hardware(seqsBis, 'RB/RB') # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) for seq in zip(*seqs): # Start sequence with concur: for q in qubits: init(q) for pulseNums in zip(*seq): with concur: for q, c in zip(qubits, pulseNums): AC(q, c) # Measure at end of each sequence with concur: for q in qubits: MEAS(q) # FIXME: Not working in QGL2 yet # Tack on calibration create_cal_seqs((qubits), 2)
def doRabiAmp_NQubits(qubits: qreg, amps, phase, measChans: qreg, docals, calRepeats): for amp in amps: with concur: for q in qubits: init(q) Utheta(q, amp=amp, phase=phase) with concur: for m in measChans: MEAS(m) if docals: create_cal_seqs(qubits, calRepeats, measChans)
def doRamsey(): q = QubitFactory('q1') TPPIFreq=1e6 # FIXME: QGL2 doesn't deal well with the call to np.arange pulseS = [ 1.00000000e-07, 2.00000000e-07, 3.00000000e-07, 4.00000000e-07, 5.00000000e-07, 6.00000000e-07, 7.00000000e-07, 8.00000000e-07, 9.00000000e-07, 1.00000000e-06, 1.10000000e-06, 1.20000000e-06, 1.30000000e-06, 1.40000000e-06, 1.50000000e-06, 1.60000000e-06, 1.70000000e-06, 1.80000000e-06, 1.90000000e-06, 2.00000000e-06, 2.10000000e-06, 2.20000000e-06, 2.30000000e-06, 2.40000000e-06, 2.50000000e-06, 2.60000000e-06, 2.70000000e-06, 2.80000000e-06, 2.90000000e-06, 3.00000000e-06, 3.10000000e-06, 3.20000000e-06, 3.30000000e-06, 3.40000000e-06, 3.50000000e-06, 3.60000000e-06, 3.70000000e-06, 3.80000000e-06, 3.90000000e-06, 4.00000000e-06, 4.10000000e-06, 4.20000000e-06, 4.30000000e-06, 4.40000000e-06, 4.50000000e-06, 4.60000000e-06, 4.70000000e-06, 4.80000000e-06, 4.90000000e-06, 5.00000000e-06, 5.10000000e-06, 5.20000000e-06, 5.30000000e-06, 5.40000000e-06, 5.50000000e-06, 5.60000000e-06, 5.70000000e-06, 5.80000000e-06, 5.90000000e-06, 6.00000000e-06, 6.10000000e-06, 6.20000000e-06, 6.30000000e-06, 6.40000000e-06, 6.50000000e-06, 6.60000000e-06, 6.70000000e-06, 6.80000000e-06, 6.90000000e-06, 7.00000000e-06, 7.10000000e-06, 7.20000000e-06, 7.30000000e-06, 7.40000000e-06, 7.50000000e-06, 7.60000000e-06, 7.70000000e-06, 7.80000000e-06, 7.90000000e-06, 8.00000000e-06, 8.10000000e-06, 8.20000000e-06, 8.30000000e-06, 8.40000000e-06, 8.50000000e-06, 8.60000000e-06, 8.70000000e-06, 8.80000000e-06, 8.90000000e-06, 9.00000000e-06, 9.10000000e-06, 9.20000000e-06, 9.30000000e-06, 9.40000000e-06, 9.50000000e-06, 9.60000000e-06, 9.70000000e-06, 9.80000000e-06, 9.90000000e-06] #pulseSpacings=np.arange(100e-9, 10e-6, 100e-9) # Create the phases for the TPPI phases = 2*pi*TPPIFreq*pulseS # Create the basic Ramsey sequence # FIXME: QGL2 doesn't deal well with this call to zip for d,phase in zip(pulseS, phases): init(q) X90(q) Id(q, d) U90(q, phase=phase) MEAS(q) # Tack on calibration create_cal_seqs((q,), calRepeats)
def doRamsey(q:qreg, delays, TPPIFreq, calRepeats): # Create the phases for the TPPI phases = 2*pi*TPPIFreq*delays # Create the basic Ramsey sequence for d,phase in zip(delays, phases): init(q) X90(q) Id(q, length=d) U90(q, phase=phase) MEAS(q) # Tack on calibration create_cal_seqs(q, calRepeats)
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 Ramsey(qubit: qreg, pulseSpacings, TPPIFreq=0, showPlot=False, calRepeats=2, suffix=False): """ Variable pulse spacing Ramsey (pi/2 - tau - pi/2) with optional TPPI. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) pulseSpacings : pulse spacings (iterable; seconds) TPPIFreq : frequency for TPPI phase updates of second Ramsey pulse (Hz) showPlot : whether to plot (boolean) calRepeats : how many repetitions of calibration pulses (int) """ # Original: # # Create the phases for the TPPI # phases = 2*pi*TPPIFreq*pulseSpacings # # Create the basic Ramsey sequence # seqs = [[X90(qubit), Id(qubit, d), U90(qubit, phase=phase), MEAS(qubit)] # for d,phase in zip(pulseSpacings, phases)] # # Tack on the calibration scalings # seqs += create_cal_seqs((qubit,), calRepeats) # fileNames = compile_to_hardware(seqs, 'Ramsey'+('_'+qubit.label)*suffix+'/Ramsey'+('_'+qubit.label)*suffix) # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) # Create the phases for the TPPI phases = 2*pi*TPPIFreq*pulseSpacings # Creating sequences that look like this: # [['X90', 'Id', 'U90', 'M'], ['X90', 'Id', 'U90', 'M']] # Create the basic Ramsey sequence for d,phase in zip(pulseSpacings, phases): init(qubit) X90(qubit) Id(qubit, d) U90(qubit, phase=phase) MEAS(qubit) # Tack on calibration create_cal_seqs((qubit,), calRepeats) # Calculate label label = 'Ramsey'+('_'+qubit.label)*suffix fullLabel = label + '/' + label
def SingleQubitRB(qubit: qreg, seqs, showPlot=False): """ Single qubit randomized benchmarking using 90 and 180 generators. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) seqs : list of lists of Clifford group integers showPlot : whether to plot (boolean) """ # Original: # seqsBis = [] # for seq in seqs: # seqsBis.append(reduce(operator.add, [clifford_seq(c, qubit) for c in seq])) # # Add the measurement to all sequences # for seq in seqsBis: # seq.append(MEAS(qubit)) # # Tack on the calibration sequences # seqsBis += create_cal_seqs((qubit,), 2) # fileNames = compile_to_hardware(seqsBis, 'RB/RB') # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) # seqs are result of create_RB_seqs: list of lists of integers # clifford_seq() returns a sequence of pulses itself # [clifford_seq() for c in seq] # gives a list of len(seq) sequences # reduce(operator.add, listOfSequences) # gives a single sequence of all the elements in listOfSequences # So the first for loop creates a single list of sequences # I assume we're not redoing clifford_seq for seq in seqs: init(qubit) for c in seq: clifford_seq(c, qubit) MEAS(qubit) # FIXME: This doesn't work yet # Tack on calibration sequences create_cal_seqs((qubit, ), 2)
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 CPMG(qubit: qreg, numPulses, pulseSpacing, calRepeats=2): """ CPMG pulse train with fixed pulse spacing. Note this pulse spacing is centre to centre, i.e. it accounts for the pulse width Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) numPulses : number of 180 pulses; should be even (iterable) pulseSpacing : spacing between the 180's (seconds) calRepeats : how many times to repeat calibration scalings (default 2) """ # Original: # # First setup the t-180-t block # CPMGBlock = [Id(qubit, (pulseSpacing-qubit.pulse_params['length'])/2), # Y(qubit), Id(qubit, (pulseSpacing-qubit.pulse_params['length'])/2)] # seqs = [[X90(qubit)] + CPMGBlock*rep + [X90(qubit), MEAS(qubit)] for rep in numPulses] # # Tack on the calibration scalings # seqs += create_cal_seqs((qubit,), calRepeats) # fileNames = compile_to_hardware(seqs, 'CPMG/CPMG') # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) # Create numPulses sequences for rep in numPulses: init(qubit) X90(qubit) # Repeat the t-180-t block rep times for _ in range(rep): pulseCentered(qubit, Id, pulseSpacing) Y(qubit) pulseCentered(qubit, Id, pulseSpacing) X90(qubit) MEAS(qubit) # Tack on calibration create_cal_seqs(qubit, calRepeats)
def TwoQubitRB(q1: qreg, q2: qreg, seqs, showPlot=False, suffix=""): """ Two qubit randomized benchmarking using 90 and 180 single qubit generators and ZX90 Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) seqs : list of lists of Clifford group integers showPlot : whether to plot (boolean) """ # Original: # seqsBis = [] # for seq in seqs: # seqsBis.append(reduce(operator.add, [clifford_seq(c, q1, q2) for c in seq])) # # Add the measurement to all sequences # for seq in seqsBis: # seq.append(MEAS(q1, q2)) # # Tack on the calibration sequences # seqsBis += create_cal_seqs((q1,q2), 2) # fileNames = compile_to_hardware(seqsBis, 'RB/RB', suffix=suffix) # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) for seq in seqs: with concur: init(q1) init(q2) for c in seq: clifford_seq(c, q1, q2) with concur: MEAS(q1) MEAS(q2) # Tack on the calibration sequences create_cal_seqs((q1, q2), 2)
def TwoQubitRB(q1: qreg, q2: qreg, seqs, add_cals=True): """ Two qubit randomized benchmarking using 90 and 180 single qubit generators and ZX90 Parameters ---------- q1,q2 : logical channels to implement sequence (LogicalChannel) seqs : list of lists of Clifford group integers """ # Original: # seqsBis = [] # for seq in seqs: # seqsBis.append(reduce(operator.add, [clifford_seq(c, q1, q2) for c in seq])) # # Add the measurement to all sequences # for seq in seqsBis: # seq.append(MEAS(q1, q2)) # # Tack on the calibration sequences # if add_cals: # seqsBis += create_cal_seqs((q1,q2), 2) # axis_descriptor = [{ # 'name': 'length', # 'unit': None, # 'points': list(map(len, seqs)), # 'partition': 1 # }] # metafile = compile_to_hardware(seqsBis, 'RB/RB', axis_descriptor = axis_descriptor, suffix = suffix, extra_meta = {'sequences':seqs}) bothQs = QRegister(q1, q2) for seq in seqs: init(bothQs) for c in seq: clifford_seq(c, q2, q1) measConcurrently(bothQs) # Tack on the calibration sequences if add_cals: create_cal_seqs((q1, q2), 2)
def EchoCRLen(controlQ: qreg, targetQ: qreg, lengths, riseFall=40e-9, amp=1, phase=0, calRepeats=2, canc_amp=0, canc_phase=np.pi/2): """ Variable length 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) 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 of repetitions of readout calibrations for each 2-qubit state """ # Original: # seqs = [[Id(controlQ)] + echoCR(controlQ, targetQ, length=l, phase=phase, riseFall=riseFall) + [Id(controlQ), MEAS(targetQ)*MEAS(controlQ)] \ # for l in lengths]+ [[X(controlQ)] + echoCR(controlQ, targetQ, length=l, phase= phase, riseFall=riseFall) + [X(controlQ), MEAS(targetQ)*MEAS(controlQ)] \ # for l in lengths] + create_cal_seqs((targetQ,controlQ), calRepeats, measChans=(targetQ,controlQ)) cNt = QRegister(controlQ, targetQ) # Sequence1: for l in lengths: init(cNt) Id(controlQ) echoCR(controlQ, targetQ, length=l, phase=phase, amp=amp, riseFall=riseFall, canc_amp=canc_amp, canc_phase=canc_phase) Id(controlQ) measConcurrently(cNt) # Sequence 2 for l in lengths: init(cNt) X(controlQ) echoCR(controlQ, targetQ, length=l, phase=phase, amp=amp, riseFall=riseFall, canc_amp=canc_amp, canc_phase=canc_phase) X(controlQ) measConcurrently(cNt) # Then do calRepeats calibration sequences create_cal_seqs(cNt, calRepeats)
def doSwap(qubit: qreg, mqubit: qreg, delays): # Original: # seqs = [[X(qubit), X(mqubit), Id(mqubit, d), MEAS(mqubit)*MEAS(qubit)] for d in delays] + create_cal_seqs((mqubit,qubit), 2, measChans=(mqubit,qubit)) # fileNames = compile_to_hardware(seqs, 'Rabi/Rabi') # print(fileNames) # if showPlot: # plotWin = plot_pulse_files(fileNames) # return plotWin for d in delays: with concur: init(qubit) init(mqubit) X(qubit) X(mqubit) Id(mqubit, d) with concur: MEAS(mqubit) MEAS(qubit) create_cal_seqs((mqubit, qubit), 2)
def SingleQubitRB_AC(qubit: qreg, seqs, showPlot=False): """ Single qubit randomized benchmarking using atomic Clifford pulses. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) seqFile : file containing sequence strings showPlot : whether to plot (boolean) """ # Original: # seqsBis = [] # for seq in seqs: # seqsBis.append([AC(qubit, c) for c in seq]) # # Add the measurement to all sequences # for seq in seqsBis: # seq.append(MEAS(qubit)) # # Tack on the calibration sequences # seqsBis += create_cal_seqs((qubit,), 2) # fileNames = compile_to_hardware(seqsBis, 'RB/RB') # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) # AC() gives a single pulse on qubit for seq in seqs: init(qubit) for c in seq: AC(qubit, c) MEAS(qubit) # Tack on calibration sequences create_cal_seqs((qubit, ), 2)
def HahnEcho(qubit: qreg, pulseSpacings, periods=0, calRepeats=2): """ A single pulse Hahn echo with variable phase of second pi/2 pulse. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) pulseSpacings : pulse spacings to sweep over; the t in 90-t-180-t-180 (iterable) periods: number of artificial oscillations calRepeats : how many times to repeat calibration scalings (default 2) """ # Original: # seqs=[]; # for k in range(len(pulseSpacings)): # seqs.append([X90(qubit), Id(qubit, pulseSpacings[k]), Y(qubit), Id(qubit,pulseSpacings[k]), \ # U90(qubit,phase=2*pi*periods/len(pulseSpacings)*k), MEAS(qubit)]) # # Tack on the calibration scalings # seqs += create_cal_seqs((qubit,), calRepeats) # fileNames = compile_to_hardware(seqs, 'Echo/Echo') # print(fileNames) # if showPlot: # plot_pulse_files(fileNames) for k in range(len(pulseSpacings)): init(qubit) X90(qubit) # FIXME 9/28/16: Must name the length arg (issue #45) Id(qubit, length=pulseSpacings[k]) Y(qubit) Id(qubit, length=pulseSpacings[k]) U90(qubit, phase=2 * pi * periods / len(pulseSpacings) * k) MEAS(qubit) create_cal_seqs(qubit, calRepeats)
def Swap(qubit: qreg, delays, mqubit: qreg = None): # Note: Not a QGL1 basic sequence any more, but preserving this anyhow # Original: # seqs = [[X(qubit), X(mqubit), Id(mqubit, d), MEAS(mqubit)*MEAS(qubit)] for d in delays] + create_cal_seqs((mqubit,qubit), 2, measChans=(mqubit,qubit)) # fileNames = compile_to_hardware(seqs, 'Rabi/Rabi') # print(fileNames) # if showPlot: # plotWin = plot_pulse_files(fileNames) # return plotWin if mqubit is None: mqubit = qubit allChans = QRegister(qubit, mqubit) for d in delays: init(allChans) X(qubit) X(mqubit) Id(mqubit, length=d) measConcurrently(allChans) create_cal_seqs(allChans, 2)
def SingleQubitRB(qubit: qreg, seqs, purity=False, add_cals=True): """ Single qubit randomized benchmarking using 90 and 180 generators. Parameters ---------- qubit : logical channel to implement sequence (LogicalChannel) seqs : list of lists of Clifford group integers """ # Original: # seqsBis = [] # op = [Id(qubit, length=0), Y90m(qubit), X90(qubit)] # for ct in range(3 if purity else 1): # for seq in seqs: # seqsBis.append(reduce(operator.add, [clifford_seq(c, qubit) for c in seq])) # #append tomography pulse to measure purity # seqsBis[-1].append(op[ct]) # # Add the measurement to all sequences # seqsBis[-1].append(MEAS(qubit)) # # Tack on the calibration sequences # if add_cals: # seqsBis += create_cal_seqs((qubit,), 2) # axis_descriptor = [{ # 'name': 'length', # 'unit': None, # 'points': list(map(len, seqs)), # 'partition': 1 # }] # metafile = compile_to_hardware(seqsBis, 'RB/RB', axis_descriptor = axis_descriptor, extra_meta = {'sequences':seqs}) # seqs are result of create_RB_seqs: list of lists of integers # clifford_seq() returns a sequence of pulses itself # [clifford_seq() for c in seq] # gives a list of len(seq) sequences # reduce(operator.add, listOfSequences) # gives a single sequence of all the elements in listOfSequences # So the first for loop creates a single list of sequences ops = [Id] if purity: ops = [Id, Y90m, X90] for op in ops: for seq in seqs: init(qubit) for c in seq: clifford_seq(c, qubit) # append tomography pulse to measure purity if op == Id: op(qubit, length=0) else: op(qubit) # append measurement MEAS(qubit) if add_cals: # Tack on calibration sequences create_cal_seqs(qubit, 2)
def BitFlip3(data_qs: qreg, ancilla_qs: qreg, theta=None, phi=None, nrounds=1, meas_delay=1e-6, docals=False, calRepeats=2): """ Encoding on 3-qubit bit-flip code, followed by n rounds of syndrome detection, and final correction using the n results. Parameters ---------- data_qs : tuple of logical channels for the 3 code qubits ancilla_qs: tuple of logical channels for the 2 syndrome qubits theta, phi: longitudinal and azimuthal rotation angles for encoded state (default = no encoding) meas_delay : delay between syndrome check rounds docals, calRepeats: enable calibration sequences, repeated calRepeats times Returns ------- metafile : metafile path """ if len(data_qs) != 3 or len(ancilla_qs) != 2: raise Exception("Wrong number of qubits") # Call some TDM Instructions DecodeSetRounds(1, 0, nrounds) Invalidate(10, 2 * nrounds) Invalidate(11, 0x1) # encode single-qubit state into 3 qubits if theta and phi: Utheta(data_qs[1], angle=theta, phase=phi) CNOT(data_qs[1], data_qs[0]) CNOT(data_qs[1], data_qs[2]) # multiple rounds of syndrome measurements for n in range(nrounds): Barrier(data_qs[0], ancilla_qs[0], data_qs[1], ancilla_qs[1]) CNOT(data_qs[0], ancilla_qs[0]) CNOT(data_qs[1], ancilla_qs[1]) Barrier(data_qs[1], ancilla_qs[0], data_qs[2], ancilla_qs[1]) CNOT(data_qs[1], ancilla_qs[0]) CNOT(data_qs[2], ancilla_qs[1]) Barrier(ancilla_qs[0], ancilla_qs[1]) MEASA(ancilla_qs[0], maddr=(10, 2 * n)) MEASA(ancilla_qs[1], maddr=(10, 2 * n + 1)) Id(ancilla_qs[0], meas_delay) # virtual msmt's just to keep the number of segments uniform across digitizer channels Barrier(data_qs) MEAS(data_qs[0], amp=0) MEAS(data_qs[1], amp=0) MEAS(data_qs[2], amp=0) Decode(10, 11, 2 * nrounds) qwait("RAM", 11) Barrier(data_qs, ancilla_qs) # virtual msmt's MEAS(data_qs[0]) MEAS(data_qs[1]) MEAS(data_qs[2]) MEAS(ancilla_qs[0], amp=0) MEAS(ancilla_qs[1], amp=0) # FIXME: What's right way to do this bit # apply corrective pulses depending on the decoder result FbGates = [] for q in data_qs: FbGates.append([gate(q) for gate in [Id, X]]) FbSeq = [reduce(operator.mul, x) for x in product(*FbGates)] for k in range(8): qif(k, [FbSeq[k]]) if docals: create_cal_seqs(qubits, calRepeats)
def Reset(qubits: qreg, measDelay=1e-6, signVec=None, doubleRound=True, buf=20e-9, measChans=None, docals=True, calRepeats=2, reg_size=None, TDM_map=None): """ Preparation, simultanoeus reset, and measurement of an arbitrary number of qubits Parameters ---------- qubits : tuple of logical channels to implement sequence (LogicalChannel) measDelay : delay between end of measuerement and reset pulse / LOADCMP signVec : Measurement results that indicate that we should flip Tuple of 0 (flip if signal > threshold or 1 for each qubit. (default == 0 for all qubits) doubleRound : if true, double round of feedback docals : enable calibration sequences calRepeats: number of times to repeat calibration reg_size: total number of qubits, including those that are not reset. Default set to len(qubits) TDM_map: map each qubit to a TDM digital input. Default: np.array(qN, qN-1, ..., q1) from MSB to LSB. """ if measChans is None: measChans = qubits if signVec is None: signVec = (0, ) * len(qubits) # FIXME: create_cal_seqs does pulses, doesn't return them # So what is old code expecting is returned here, that I can use instead? # given numRepeats=1, this is a single [] containing 2*#qubits of the reduce() thing # The reduce thing is a bunch of pulses with * between them # So here I create the combinations of pulses we want for each prep thing and loop over those combos for prep in product([Id, X], repeat=len(qubits)): init(qubits) prep # FIXME: See below where it did another loop? Look at git history? # FIXME: Could I start by making qreset a qgl1 stub? # Seems like the old qgl2 pushed into this method some of what new qgl1 qreset does itself # so a git diff is key qreset(qubits, signVec, measDelay, buf, reg_size=reg_size, TDM_map=TDM_map) measConcurrently(qubits) if doubleRound: qreset(qubits, signVec, measDelay, buf, reg_size=reg_size, TDM_map=TDM_map) # Add final measurement measConcurrently(qubits) Id(qubits[0], length=measDelay) qwait(kind='CMP') # If we're doing calibration too, add that at the very end # - another 2^numQubits * calRepeats sequences if docals: create_cal_seqs(qubits, calRepeats, measChans=measChans, waitcmp=True) # metafile = compile_to_hardware(seqs, 'Reset/Reset') # old version for prep in product([Id, X], repeat=len(qubits)): for p, q, measSign in zip(prep, qubits, signVec): init(q) # prepare the initial state p(q) qreset_full(q, measDelay, measSign) if doubleRound: qreset_full(q, measDelay, measSign) MEAS(qubits) # If we're doing calibration too, add that at the very end # - another 2^numQubits * calRepeats sequences if docals: create_cal_seqs(qubits, calRepeats)