Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
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)
Пример #9
0
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)
Пример #10
0
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)
Пример #11
0
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)
Пример #12
0
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)
Пример #13
0
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)
Пример #14
0
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)
Пример #15
0
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
Пример #16
0
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)
Пример #17
0
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)
Пример #18
0
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)
Пример #19
0
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)
Пример #20
0
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)
Пример #21
0
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)
Пример #22
0
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)
Пример #23
0
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)
Пример #24
0
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)
Пример #25
0
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)
Пример #26
0
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)
Пример #27
0
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)
Пример #28
0
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)