Beispiel #1
0
def RabiWidth(qubit, widths, amp=1, phase=0, shapeFun=QGL.PulseShapes.tanh, showPlot=False):
    """
    Variable pulse width Rabi nutation experiment.

    Parameters
    ----------
    qubit : logical channel to implement sequence (LogicalChannel)
    widths : pulse widths to sweep over (iterable)
    phase : phase of the pulse (radians, default = 0)
    shapeFun : shape of pulse (function, default = PulseShapes.tanh)
    showPlot : whether to plot (boolean)
    """

    resFunction = compile_function(
        os.path.relpath(__file__),
        "doRabiWidth"
        (qubit, widths, amp, phase, shapeFun)
        )
    seqs = resFunction()
    return seqs

    fileNames = qgl2_compile_to_hardware(seqs, "Rabi/Rabi")
    print(fileNames)
    if showPlot:
        plot_pulse_files(fileNames)
Beispiel #2
0
def RabiAmp_NQubitsq1(qubits, amps, phase=0, showPlot=False,
                    measChans=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)
    showPlot : whether to plot (boolean)
    measChans : tuble of qubits to be measured (LogicalChannel)
    docals, calRepeats: enable calibration sequences, repeated calRepeats times
    """

    if measChans is None:
        measChans = qubits

    resFunction = compile_function(
        os.path.relpath(__file__),
        "doRabiWidth",
        (qubits, amps, phase, measChans, docals, calRepeats)
        )
    seqs = resFunction()
    return seqs

    fileNames = qgl2_compile_to_hardware(seqs, "Rabi/Rabi")
    print(fileNames)
    if showPlot:
        plot_pulse_files(fileNames)
Beispiel #3
0
def main():
    from pyqgl2.qreg import QRegister
    import pyqgl2.test_cl
    from pyqgl2.main import compile_function, qgl2_compile_to_hardware
    import numpy as np

    toHW = True
    plotPulses = False
    pyqgl2.test_cl.create_default_channelLibrary(toHW, True)

    #    # To turn on verbose logging in compile_function
    #    from pyqgl2.ast_util import NodeError
    #    from pyqgl2.debugmsg import DebugMsg
    #    NodeError.MUTE_ERR_LEVEL = NodeError.NODE_ERROR_NONE
    #    DebugMsg.set_level(0)

    # Now compile the QGL2 to produce the function that would generate the expected sequence.
    # Supply the path to the QGL2, the main function in that file, and a list of the args to that function.
    # Can optionally supply saveOutput=True to save the qgl1.py
    # file,
    # and intermediate_output="path-to-output-file" to save
    # intermediate products

    # Pass in QRegister(s) NOT real Qubits
    q1 = QRegister("q1")

    # FIXME: See issue #44: Must supply all args to qgl2main for now

    #    for func, args, label in [("HahnEcho", (q1, np.linspace(0, 5e-6, 11)), "HahnEcho"),
    #                              ("CPMG", (q1, [0, 2, 4, 5], 500e-9), "CPMG"),
    #                          ]:
    for func, args, label in [
        ("HahnEcho", (q1, np.linspace(0, 5e-6, 11), 0, 2), "HahnEcho"),
        ("CPMG", (q1, [0, 2, 4, 6], 500e-9, 2), "CPMG"),
    ]:

        print(f"\nRun {func}...")
        # Here we know the function is in the current file
        # You could use os.path.dirname(os.path.realpath(__file)) to find files relative to this script,
        # Or os.getcwd() to get files relative to where you ran from. Or always use absolute paths.
        resFunc = compile_function(__file__, func, args)
        # Run the QGL2. Note that the generated function takes no arguments itself
        seq = resFunc()
        if toHW:
            print(f"Compiling {func} sequences to hardware\n")
            fileNames = qgl2_compile_to_hardware(seq, f'{label}/{label}')
            print(f"Compiled sequences; metafile = {fileNames}")
            if plotPulses:
                from QGL.PulseSequencePlotter import plot_pulse_files
                # FIXME: As called, this returns a graphical object to display
                plot_pulse_files(fileNames)
        else:
            print(f"\nGenerated {func} sequences:\n")
            from QGL.Scheduler import schedule

            scheduled_seq = schedule(seq)
            from IPython.lib.pretty import pretty
            print(pretty(scheduled_seq))
Beispiel #4
0
def main():
    from pyqgl2.qreg import QRegister
    import pyqgl2.test_cl
    from pyqgl2.main import compile_function, qgl2_compile_to_hardware
    import numpy as np

    toHW = True
    plotPulses = True
    pyqgl2.test_cl.create_default_channelLibrary(toHW, True)

    #    # To turn on verbose logging in compile_function
    #    from pyqgl2.ast_util import NodeError
    #    from pyqgl2.debugmsg import DebugMsg
    #    NodeError.MUTE_ERR_LEVEL = NodeError.NODE_ERROR_NONE
    #    DebugMsg.set_level(0)

    # Now compile the QGL2 to produce the function that would generate the expected sequence.
    # Supply the path to the QGL2, the main function in that file, and a list of the args to that function.
    # Can optionally supply saveOutput=True to save the qgl1.py
    # file,
    # and intermediate_output="path-to-output-file" to save
    # intermediate products

    # Pass in a QRegister NOT the real Qubit
    q = QRegister(1)

    # SPAM(q1, np.linspace(0, pi/2, 11))
    # - test_basic_mins uses np.linspace(0,1,11)

    # Here we know the function is in the current file
    # You could use os.path.dirname(os.path.realpath(__file)) to find files relative to this script,
    # Or os.getcwd() to get files relative to where you ran from. Or always use absolute paths.
    resFunction = compile_function(__file__, "SPAM",
                                   (q, np.linspace(0, pi / 2, 11), 10))
    # Run the QGL2. Note that the generated function takes no arguments itself
    sequences = resFunction()
    if toHW:
        print("Compiling sequences to hardware\n")
        fileNames = qgl2_compile_to_hardware(sequences, filename='SPAM/SPAM')
        print(f"Compiled sequences; metafile = {fileNames}")
        if plotPulses:
            from QGL.PulseSequencePlotter import plot_pulse_files
            # FIXME: As called, this returns a graphical object to display
            plot_pulse_files(fileNames)
    else:
        print("\nGenerated sequences:\n")
        from QGL.Scheduler import schedule

        scheduled_seq = schedule(sequences)
        from IPython.lib.pretty import pretty
        print(pretty(scheduled_seq))
Beispiel #5
0
def PulsedSpec(qubit, specOn=True, showPlot=False):
    """
    Measurement preceded by a qubit pulse if specOn = True
    """
    resFunction = compile_function(
        os.path.relpath(__file__),
        "doSingleShot",
        (qubit,)
        )
    seqs = resFunction()
    return seqs

    fileNames = qgl2_compile_to_hardware(seqs, "Spec/Spec")
    print(fileNames)
    if showPlot:
        plot_pulse_files(fileNames)
Beispiel #6
0
def SingleShot(qubit: qreg, showPlot=False):
    """
    2-segment sequence with qubit prepared in |0> and |1>, useful for single-shot fidelity measurements and kernel calibration
    """
    resFunction = compile_function(
        os.path.relpath(__file__),
        "doSingleShot",
        (qubit,)
        )
    seqs = resFunction()
    return seqs

    fileNames = qgl2_compile_to_hardware(seqs, "SingleShot/SingleShot")
    print(fileNames)
    if showPlot:
        plot_pulse_files(fileNames)
Beispiel #7
0
def RabiAmp(qubit, amps, phase=0, showPlot=False):
    """
    Variable amplitude Rabi nutation experiment.

    Parameters
    ----------
    qubit : logical channel to implement sequence (LogicalChannel)
    amps : pulse amplitudes to sweep over (iterable)
    phase : phase of the pulse (radians)
    showPlot : whether to plot (boolean)
    """
    resFunction = compile_function(
        os.path.relpath(__file__),
        "doRabiAmp",
        (qubit, amps, phase)
        )
    seqs = resFunction()
    return seqs

    fileNames = qgl2_compile_to_hardware(seqs, "Rabi/Rabi")
    print(fileNames)
    if showPlot:
        plot_pulse_files(fileNames)
Beispiel #8
0
def main():
    from pyqgl2.qreg import QRegister
    import pyqgl2.test_cl
    from pyqgl2.main import compile_function, qgl2_compile_to_hardware
    import numpy as np

    toHW = True
    plotPulses = False  # This tries to produce graphics to display
    pyqgl2.test_cl.create_default_channelLibrary(toHW, True)

    #    # To turn on verbose logging in compile_function
    #    from pyqgl2.ast_util import NodeError
    #    from pyqgl2.debugmsg import DebugMsg
    #    NodeError.MUTE_ERR_LEVEL = NodeError.NODE_ERROR_NONE
    #    DebugMsg.set_level(0)

    # Now compile the QGL2 to produce the function that would generate the expected sequence.
    # Supply the path to the QGL2, the main function in that file, and a list of the args to that function.
    # Can optionally supply saveOutput=True to save the qgl1.py
    # file,
    # and intermediate_output="path-to-output-file" to save
    # intermediate products

    # Pass in QRegister(s) NOT real Qubits
    q1 = QRegister("q1")

    # Axis Descriptor generator functions here
    # This is ugly; they're method dependent, but I can't do them in the QGL2 itself
    # Additionally, each uses values from the args to the function
    # So here we make those arguments be constants so we can use them twice
    # without rewriting the values
    hahnSpacings = np.linspace(0, 5e-6, 11)
    tCalR = 2  # calRepeats
    cpmgNumPulses = [0, 2, 4, 6]
    cpmgSpacing = 500e-9

    def getHahnAxisDesc(pulseSpacings, calRepeats):
        return [
            delay_descriptor(2 * pulseSpacings),
            cal_descriptor(('qubit', ), calRepeats)
        ]

    def getCPMGAxisDesc(pulseSpacing, numPulses, calRepeats):
        return [
            # NOTE: numPulses is not a numpy array, so cannot multiply by a float
            # But thankfully, np.array(np.array) = np.array so this is always a good move here.
            delay_descriptor(pulseSpacing * np.array(numPulses)),
            cal_descriptor(('qubit', ), calRepeats)
        ]

    # FIXME: See issue #44: Must supply all args to qgl2main for now


#    for func, args, label, axisDesc in [("HahnEcho", (q1, hahnSpacings), "Echo", getHahnAxisDesc(hahnSpacings, tCalR)),
#                              ("CPMG", (q1, cpmgNumPulses, cpmgSpacing), "CPMG", getCPMGAxisDesc(cpmgSpacing, cpmgNumPulses, tCalR)),
#                          ]:
    for func, args, label, axisDesc in [
        ("HahnEcho", (q1, hahnSpacings, 0, tCalR), "Echo",
         getHahnAxisDesc(hahnSpacings, tCalR)),
        ("CPMG", (q1, cpmgNumPulses, cpmgSpacing, tCalR), "CPMG",
         getCPMGAxisDesc(cpmgSpacing, cpmgNumPulses, tCalR)),
    ]:

        print(f"\nRun {func}...")
        # Here we know the function is in the current file
        # You could use os.path.dirname(os.path.realpath(__file)) to find files relative to this script,
        # Or os.getcwd() to get files relative to where you ran from. Or always use absolute paths.
        resFunc = compile_function(__file__, func, args)
        # Run the QGL2. Note that the generated function takes no arguments itself
        seq = resFunc()
        if toHW:
            print(f"Compiling {func} sequences to hardware\n")
            fileNames = qgl2_compile_to_hardware(seq,
                                                 filename=f'{label}/{label}',
                                                 axis_descriptor=axisDesc)
            print(f"Compiled sequences; metafile = {fileNames}")
            if plotPulses:
                from QGL.PulseSequencePlotter import plot_pulse_files
                # FIXME: As called, this returns a graphical object to display
                plot_pulse_files(fileNames)
        else:
            print(f"\nGenerated {func} sequences:\n")
            from QGL.Scheduler import schedule

            scheduled_seq = schedule(seq)
            from IPython.lib.pretty import pretty
            print(pretty(scheduled_seq))
Beispiel #9
0
def SingleQubitRBT(qubit: qreg,
                   seqFileDir,
                   analyzedPulse: pulse,
                   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:
    # # Setup a pulse library
    # pulseLib = [AC(qubit, cliffNum) for cliffNum in range(24)]
    # pulseLib.append(analyzedPulse)
    # measBlock = MEAS(qubit)

    # seqs = []
    # for ct in range(10):
    #     fileName = 'RBT_Seqs_fast_{0}_F1.txt'.format(ct+1)
    #     tmpSeqs = []
    #     with open(os.path.join(seqFileDir, fileName),'r') as FID:
    #         fileReader = reader(FID)
    #         for pulseSeqStr in fileReader:
    #             seq = []
    #             for pulseStr in pulseSeqStr:
    #                 seq.append(pulseLib[int(pulseStr)-1])
    #             seq.append(measBlock)
    #             tmpSeqs.append(seq)
    #         seqs += tmpSeqs[:12]*12 + tmpSeqs[12:-12] + tmpSeqs[-12:]*12

    # seqsPerFile = 100
    # numFiles = len(seqs)//seqsPerFile

    # for ct in range(numFiles):
    #     chunk = seqs[ct*seqsPerFile:(ct+1)*seqsPerFile]
    #     # Tack on the calibration scalings
    #     numCals = 4
    #     chunk += [[Id(qubit), measBlock]]*numCals + [[X(qubit), measBlock]]*numCals
    #     fileNames = compile_to_hardware(chunk, 'RBT/RBT', suffix='_{0}'.format(ct+1))

    # if showPlot:
    #     plot_pulse_files(fileNames)

    pulseSeqStrs = []
    for ct in range(10):
        fileName = 'RBT_Seqs_fast_{0}_F1.txt'.format(ct + 1)
        tmpSeqs = []
        with open(os.path.join(seqFileDir, fileName), 'r') as FID:
            fileReader = reader(FID)
            for pulseSeqStr in fileReader:
                tmpSeqs.append(pulseSeqStr)
            pulseSeqStrs = tmpSeqs[:12] * 12 + tmpSeqs[
                12:-12] + tmpSeqs[-12:] * 12

    numSeqs = len(pulseSeqStrs)
    seqsPerFile = 100
    numFiles = numSeqs // seqsPerFile
    numCals = 4

    for ct in range(numFiles):
        for s in range(seqsPerFile):
            init(qubit)
            seqStr = pulseSeqStrs[ct * seqsPerFile + s]
            getPulseSeq(qubit, seqStr)
        # Add numCals calibration scalings
        for _ in range(numCals):
            init(qubit)
            Id(qubit)
            MEAS(qubit)

            init(qubit)
            X(qubit)
            MEAS(qubit)
        # FIXME: Then magically get the sequences here....
        # This needs to get refactored....
        # We need to split creating seqs from c_to_h
        fileNames = compile_to_hardware([],
                                        'RBT/RBT',
                                        suffix='_{0}'.format(ct + 1),
                                        qgl2=True)

    # FIXME: Do this from calling function
    if showPlot:
        plot_pulse_files(fileNames)
Beispiel #10
0
def main():
    from pyqgl2.qreg import QRegister
    import pyqgl2.test_cl
    from pyqgl2.main import compile_function, qgl2_compile_to_hardware

    toHW = True
    plotPulses = False
    pyqgl2.test_cl.create_default_channelLibrary(toHW, True)

#    # To turn on verbose logging in compile_function
#    from pyqgl2.ast_util import NodeError
#    from pyqgl2.debugmsg import DebugMsg
#    NodeError.MUTE_ERR_LEVEL = NodeError.NODE_ERROR_NONE
#    DebugMsg.set_level(0)

    # Now compile the QGL2 to produce the function that would generate the expected sequence.
    # Supply the path to the QGL2, the main function in that file, and a list of the args to that function.
    # Can optionally supply saveOutput=True to save the qgl1.py
    # file,
    # and intermediate_output="path-to-output-file" to save
    # intermediate products

    # Pass in QRegister(s) NOT real Qubits
    q1 = QRegister("q1")
    q2 = QRegister("q2")

    # Axis Descriptor generator functions here
    # This is ugly; they're method dependent, but I can't do them in the QGL2 itself
    # Additionally, each uses values from the args to the function
    # So here we make those arguments be constants so we can use them twice
    # without rewriting the values
    pirlengths = np.linspace(0, 4e-6, 11) # Lengths arg to PiRabi
    eclLengths = np.linspace(0, 2e-6, 11) # Lengths arg to EchoCRLen
    trisefall = 40e-9 # riseFall arg for many
    tamp = 1 # amp arg for many
    t2amp = 0.8 # amp arg for CRTomo
    tphase = 0 # phase arg for many
    tcalr = 2 # calRepeats arg for many
    ecpPhases = np.linspace(0, np.pi/2, 11) # phases arg for EchoCRPhase
    ecaAmps = np.linspace(0, 5e-6, 11) # amps arg for echoCRAmp
    crtLengths = np.linspace(0, 2e-6, 11) # lengths arg for CRtomo_seq
    def getPRAxisDesc(lengths, calRepeats):
        return [
            delay_descriptor(np.concatenate((lengths, lengths))),
            # Hard code there are 2 qubits
            cal_descriptor(('c', 't'), calRepeats)
        ]
    def getECLAxisDesc(lengths, calRepeats):
        return [
            delay_descriptor(np.concatenate((lengths, lengths))),
            # Hard code there are 2 qubits
            cal_descriptor(('controlQ', 'targetQ'), calRepeats)
        ]
    def getECPAxisDesc(phases, calRepeats):
        return [
            {
                'name': 'phase',
                'unit': 'radians',
                'points': list(phases)+list(phases),
                'partition': 1
            },
            cal_descriptor(('controlQ', 'targetQ'), calRepeats)
        ]
    def getECAAxisDesc(amps, calRepeats):
        return [
            {
                'name': 'amplitude',
                'unit': None,
                'points': list(amps)+list(amps),
                'partition': 1
            },
            cal_descriptor(('controlQ', 'targetQ'), calRepeats)
        ]
    def getCRtAxisDesc(lengths):
        return [
            delay_descriptor(np.concatenate((np.repeat(lengths,3), np.repeat(lengths,3)))),
            cal_descriptor(('targetQ',), 2)
        ]

    # FIXME: See issue #44: Must supply all args to qgl2main for now

#    for func, args, label, axisDesc in [("PiRabi", (q1, q2, pirlengths), "PiRabi", getPRAxisDesc(pirlengths, tcalr)),
#                              ("EchoCRLen", (q1, q2, np.linspace(0, 2e-6, 11)), "EchoCR", getECLAxisDesc(eclLengths, tcalr)),
#                              ("EchoCRPhase", (q1, q2, np.linspace(0, np.pi/2, 11)), "EchoCR", getECPAxisDesc(ecpPhases, tcalr)),
#                              ("EchoCRAmp", (q1, q2, np.linspace(0, 5e-6, 11)), "EchoCR", getECAAxisDesc(ecaAmps, tcalr)), # FIXME: Right values?
#                              ("CRtomo_seq", (q1, q2, np.linspace(0, 2e-6, 11), 0), "CR", getCRtAxisDesc(crtLengths)) # FIXME: Right values?
#                          ]:
    for func, args, label, axisDesc in [("PiRabi", (q1, q2, pirlengths, trisefall,tamp,tphase,tcalr), "PiRabi", getPRAxisDesc(pirlengths, tcalr)),
                              ("EchoCRLen", (q1, q2, eclLengths, trisefall, tamp, tphase, tcalr, 0, np.pi/2), "EchoCR", getECLAxisDesc(eclLengths, tcalr)),
                              ("EchoCRPhase", (q1, q2, ecpPhases, trisefall,tamp,100e-9,tcalr,0,np.pi/2), "EchoCR", getECPAxisDesc(ecpPhases, tcalr)),
                              ("EchoCRAmp", (q1, q2, ecaAmps, trisefall,50e-9,tphase,tcalr), "EchoCR", getECAAxisDesc(ecaAmps, tcalr)), # FIXME: Right values?
                              ("CRtomo_seq", (q1, q2, crtLengths, 0, t2amp,20e-9), "CR", getCRtAxisDesc(crtLengths)) # FIXME: Right values?
                          ]:

        print(f"\nRun {func}...")
        # Here we know the function is in the current file
        # You could use os.path.dirname(os.path.realpath(__file)) to find files relative to this script,
        # Or os.getcwd() to get files relative to where you ran from. Or always use absolute paths.
        resFunc = compile_function(__file__, func, args)
        # Run the QGL2. Note that the generated function takes no arguments itself
        seq = resFunc()
        if toHW:
            print(f"Compiling {func} sequences to hardware\n")
            fileNames = qgl2_compile_to_hardware(seq, filename=f'{label}/{label}', axis_descriptor=axisDesc)
            print(f"Compiled sequences; metafile = {fileNames}")
            if plotPulses:
                from QGL.PulseSequencePlotter import plot_pulse_files
                # FIXME: As called, this returns a graphical object to display
                plot_pulse_files(fileNames)
        else:
            print(f"\nGenerated {func} sequences:\n")
            from QGL.Scheduler import schedule

            scheduled_seq = schedule(seq)
            from IPython.lib.pretty import pretty
            print(pretty(scheduled_seq))
Beispiel #11
0
def main():
    from pyqgl2.qreg import QRegister
    import pyqgl2.test_cl
    from pyqgl2.main import compile_function, qgl2_compile_to_hardware

    toHW = True
    plotPulses = False # Don't try creating graphics objects
    suffix = False # change generated filename to include qbit name
    pyqgl2.test_cl.create_default_channelLibrary(toHW, True)

#    # To turn on verbose logging in compile_function
#    from pyqgl2.ast_util import NodeError
#    from pyqgl2.debugmsg import DebugMsg
#    NodeError.MUTE_ERR_LEVEL = NodeError.NODE_ERROR_NONE
#    DebugMsg.set_level(0)

    # Now compile the QGL2 to produce the function that would generate the expected sequence.
    # Supply the path to the QGL2, the main function in that file, and a list of the args to that function.
    # Can optionally supply saveOutput=True to save the qgl1.py
    # file,
    # and intermediate_output="path-to-output-file" to save
    # intermediate products

    # Pass in QRegister(s) NOT real Qubits
    qbitName = "q1"
    q1 = QRegister(qbitName)

    # FIXME: See issue #44: Must supply all args to qgl2main for now

    # InversionRecovery(q1,  np.linspace(0, 5e-6, 11))
    # Ramsey(q1, np.linspace(0, 5e-6, 11))

    irDelays = np.linspace(0, 5e-6, 11)
    rSpacings = np.linspace(0, 5e-6, 11)
    tCalR = 2

    def irAD(delays, calRepeats):
        return [
            delay_descriptor(delays),
            cal_descriptor(('qubit',), calRepeats)
            ]

    def rAD(pulseSpacings, calRepeats):
        return [
            delay_descriptor(pulseSpacings),
            cal_descriptor(('qubit',), calRepeats)
        ]

#    for func, args, label, axisDesc in [("InversionRecovery", (q1, irDelays), "T1", irAD(irDelays, tCalR)),
#                              ("Ramsey", (q1, rSpacings), "Ramsey", rAD(rSpacings, tCalR))
#                          ]:
    for func, args, label, axisDesc in [("InversionRecovery", (q1, irDelays, tCalR), "T1", irAD(irDelays, tCalR)),
                              ("Ramsey", (q1, rSpacings, 0, tCalR), "Ramsey", rAD(rSpacings, tCalR))
                          ]:

        print(f"\nRun {func}...")
        # Here we know the function is in the current file
        # You could use os.path.dirname(os.path.realpath(__file)) to find files relative to this script,
        # Or os.getcwd() to get files relative to where you ran from. Or always use absolute paths.
        resFunc = compile_function(__file__, func, args)
        # Run the QGL2. Note that the generated function takes no arguments itself
        seq = resFunc()
        if toHW:
            print(f"Compiling {func} sequences to hardware\n")

            # Generate proper filenames; for these, it isn't just the label Ramsey
            # T1T2 QGL functions take a suffix boolean default false. If true, then append to label "_qubit.label"; ie "_q1"
            if suffix:
                label = label + f"_{qbitName}"

            fileNames = qgl2_compile_to_hardware(seq, filename=f'{label}/{label}', axis_descriptor=axisDesc)
            print(f"Compiled sequences; metafile = {fileNames}")
            if plotPulses:
                from QGL.PulseSequencePlotter import plot_pulse_files
                # FIXME: As called, this returns a graphical object to display
                plot_pulse_files(fileNames)
        else:
            print(f"\nGenerated {func} sequences:\n")
            from QGL.Scheduler import schedule

            scheduled_seq = schedule(seq)
            from IPython.lib.pretty import pretty
            print(pretty(scheduled_seq))
Beispiel #12
0
def main():
    from pyqgl2.qreg import QRegister
    import pyqgl2.test_cl
    from pyqgl2.main import compile_function, qgl2_compile_to_hardware
    import numpy as np
    import QGL.PulseShapes

    toHW = True
    plotPulses = False
    pyqgl2.test_cl.create_default_channelLibrary(toHW, True)

    #    # To turn on verbose logging in compile_function
    #    from pyqgl2.ast_util import NodeError
    #    from pyqgl2.debugmsg import DebugMsg
    #    NodeError.MUTE_ERR_LEVEL = NodeError.NODE_ERROR_NONE
    #    DebugMsg.set_level(0)

    # Now compile the QGL2 to produce the function that would generate the expected sequence.
    # Supply the path to the QGL2, the main function in that file, and a list of the args to that function.
    # Can optionally supply saveOutput=True to save the qgl1.py
    # file,
    # and intermediate_output="path-to-output-file" to save
    # intermediate products

    # Pass in QRegister(s) NOT real Qubits
    q1 = QRegister("q1")
    q2 = QRegister("q2")
    qr = QRegister(q1, q2)

    rAmpAmps = np.linspace(0, 1, 1)
    rWidthWidths = np.linspace(0, 5e-6, 11)
    ranqAmps = np.linspace(0, 5e-6, 11)
    tCalR = 2
    rAmpPiAmps = np.linspace(0, 1, 11)

    def getRAmpAD(amps):
        return [{
            'name': 'amplitude',
            'unit': None,
            'points': list(amps),
            'partition': 1
        }]

    def getRWidthAD(widths):
        return [delay_descriptor(widths)]

    def getRAmpNQAD(qubits, amps, calRepeats):
        return [{
            'name': 'amplitude',
            'unit': None,
            'points': list(amps),
            'partition': 1
        },
                cal_descriptor(qubits, calRepeats)]

    def getRAmpPiAD(amps):
        return [{
            'name': 'amplitude',
            'unit': None,
            'points': list(amps),
            'partition': 1
        }]

    # FIXME: See issue #44: Must supply all args to qgl2main for now


#    for func, args, label, axisDec in [("RabiAmp", (q1, rAmpAmps), "Rabi", getRAmpAD(rAmpAmps)),
#                              ("RabiWidth", (q1, rWidthWidths), "Rabi", getRWidthAD(rWidthWidths)),
#                              ("RabiAmpPi", (q1, q2, rAmpPiAmps), "Rabi", getRAmpPiAD(rAmpPiAmps)),
#                              ("SingleShow", (q1,), "SingleShot", None),
#                              ("PulsedSpec", (q1,), "Spec", None),
#                              ("RabiAmp_NQubits", (qr,ranqAmps), "Rabi", getRAmpNQAD(qr, ranqAmps, tCalR)),
#                              ("Swap", (q1, np.linspace(0, 5e-6, 11), "Swap", None),
#                          ]:

    for func, args, label, axisDesc in [
        ("RabiAmp", (q1, rAmpAmps, 0), "Rabi", getRAmpAD(rAmpAmps)),
        ("RabiWidth", (q1, rWidthWidths, 1, 0, QGL.PulseShapes.tanh), "Rabi",
         getRWidthAD(rWidthWidths)),
        ("RabiAmpPi", (q1, q2, rAmpPiAmps, 0), "Rabi",
         getRAmpPiAD(rAmpPiAmps)), ("SingleShot", (q1, ), "SingleShot", None),
        ("PulsedSpec", (q1, True), "Spec", None),
        ("RabiAmp_NQubits", (qr, ranqAmps, 0, qr, False, tCalR), "Rabi",
         getRAmpNQAD(qr, ranqAmps, tCalR)),
        ("Swap", (q1, np.linspace(0, 5e-6, 11), q2), "Swap", None)
    ]:

        print(f"\nRun {func}...")
        # Here we know the function is in the current file
        # You could use os.path.dirname(os.path.realpath(__file)) to find files relative to this script,
        # Or os.getcwd() to get files relative to where you ran from. Or always use absolute paths.
        resFunc = compile_function(__file__, func, args)
        # Run the QGL2. Note that the generated function takes no arguments itself
        seq = resFunc()
        if toHW:
            print(f"Compiling {func} sequences to hardware\n")
            # To get verbose logging including showing the compiled sequences:
            # QGL.Compiler.set_log_level()
            fileNames = qgl2_compile_to_hardware(seq,
                                                 filename=f'{label}/{label}',
                                                 axis_descriptor=axisDesc)
            print(f"Compiled sequences; metafile = {fileNames}")
            if plotPulses:
                from QGL.PulseSequencePlotter import plot_pulse_files
                # FIXME: As called, this returns a graphical object to display
                plot_pulse_files(fileNames)
        else:
            print(f"\nGenerated {func} sequences:\n")
            from QGL.Scheduler import schedule

            scheduled_seq = schedule(seq)
            from IPython.lib.pretty import pretty
            print(pretty(scheduled_seq))
Beispiel #13
0
def main():
    from pyqgl2.qreg import QRegister
    import pyqgl2.test_cl
    from pyqgl2.main import compile_function, qgl2_compile_to_hardware
    import numpy as np
    import random

    toHW = True
    plotPulses = False
    pyqgl2.test_cl.create_default_channelLibrary(toHW, True)

#    # To turn on verbose logging in compile_function
#    from pyqgl2.ast_util import NodeError
#    from pyqgl2.debugmsg import DebugMsg
#    NodeError.MUTE_ERR_LEVEL = NodeError.NODE_ERROR_NONE
#    DebugMsg.set_level(0)

    # Now compile the QGL2 to produce the function that would generate the expected sequence.
    # Supply the path to the QGL2, the main function in that file, and a list of the args to that function.
    # Can optionally supply saveOutput=True to save the qgl1.py
    # file,
    # and intermediate_output="path-to-output-file" to save
    # intermediate products

    # Pass in QRegister(s) NOT real Qubits
    q1 = QRegister("q1")
    q2 = QRegister("q2")
    qr = QRegister(q1, q2)

    # FIXME: See issue #44: Must supply all args to qgl2main for now

    # Functions here have some extra code to run before running the compiled QGL2,
    # so define functions for those; random number seeding

    def beforeSingleRB():
        np.random.seed(20152606) # set seed for create_RB_seqs()
        random.seed(20152606) # set seed for random.choice()
    # SingleQubitRB(q1, create_RB_seqs(1, 2**np.arange(1,7)))

    # The original unit test had this comment:
    """  Fails on APS1, APS2, and Tek7000 due to:
    File "QGL/PatternUtils.py", line 129, in add_gate_pulses
    if has_gate(chan) and not pulse.isZero and not (chan.gate_chan
    AttributeError: 'CompositePulse' object has no attribute 'isZero'
    """
    def beforeTwoRB():
        np.random.seed(20152606) # set seed for create_RB_seqs()
    # TwoQubitRB(q2, q1, create_RB_seqs(2, [2, 4, 8, 16, 32], repeats=16))

    def beforeSimRBAC():
        np.random.seed(20151709) # set seed for create_RB_seqs
        #seqs1 = create_RB_seqs(1, 2**np.arange(1,7))
        #seqs2 = create_RB_seqs(1, 2**np.arange(1,7))
    # SimultaneousRB_AC((q1, q2), (seqs1, seqs2))

    def beforeSingleRBAC():
        np.random.seed(20152606) # set seed for create_RB_seqs
    # SingleQubitRB_AC(q1,create_RB_seqs(1, 2**np.arange(1,7)))

# FIXME: Add test of SingleQubitRB_DiAC

    sqCSeqs = create_RB_seqs(1, 2**np.arange(1,7))
    tqCSeqs = create_RB_seqs(2, [2, 4, 8, 16, 32], repeats=16)
    simCSeqs = (sqCSeqs, sqCSeqs)
    tAddCals = True
    def getSingleQubitRBAD(seqs, add_cals):
        ad = [{
            'name': 'length',
            'unit': None,
            'points': list(map(len, seqs)),
            'partition': 1
        }]
        if add_cals:
            ad.append(cal_descriptor(('qubit',), 2))
        return ad

    def getTwoQubitRBAD(seqs, add_cals):
        axis_descriptor = [{
            'name': 'length',
            'unit': None,
            'points': list(map(len, seqs)),
            'partition': 1
        }]
        if add_cals:
            axis_descriptor.append(cal_descriptor(('q1', 'q2'), 2))
        return axis_descriptor

    def getSingleQubitRBAC_AD(seqs, add_cals):
        axis_descriptor = [{
            'name': 'length',
            'unit': None,
            'points': list(map(len, seqs)),
            'partition': 1
        }]
        if add_cals:
            axis_descriptor.append(cal_descriptor(('qubit',), 2))
        return axis_descriptor

    def getSimRBACAD(seqs, add_cals, qubits):
        axis_descriptor = [{
            'name': 'length',
            'unit': None,
            'points': list(map(len, seqs)),
            'partition': 1
        }]
        if add_cals:
            axis_descriptor.append(cal_descriptor((qubits), 2))
        return axis_descriptor

# FIXME: SingleQubitIRB_AC filenames are more complex
# FIXME: SingleQubitRBT has complex suffix it should pass to compile_to_hardware

#    for func, args, label, beforeFunc, axisDesc, cseqs in [("SingleQubitRB", (q1, sqCSeqs), "RB", beforeSingleRB, getSingleQubitRBAD(sqCSeqs, tAddCals), sqCSeqs),
#                              ("TwoQubitRB", (q1, q2, tqCSeqs), "RB", beforeTwoRB, getTwoQubitRBAD(tqCSeqs, tAddCals), tqCSeqs),
#                              ("SingleQubitRB_AC", (q1,sqCSeqs), "RB", beforeSingleRBAC, getSingleQubitRBAC_AD(sqCSeqs, tAddCals), sqCSeqs),
#                              ("SimultaneousRB_AC", (qr, simCSeqs), "RB", beforeSimRBAC, getSimRBACAD(simCSeqs, tAddCals, qr), simCSeqs),
#                              ("SingleQubitIRB_AC", (q1,''), "RB", None, None, None),
# Comment says this next one relies on a specific file, so don't bother running
#                              ("SingleQubitRBT", (q1,'', fixmePulse), "RBT", None, None, None),
#                          ]:

    for func, args, label, beforeFunc, axisDesc, cseqs in [("SingleQubitRB", (q1, sqCSeqs, False, tAddCals), "RB", beforeSingleRB, getSingleQubitRBAD(sqCSeqs, tAddCals), sqCSeqs),
                              ("TwoQubitRB", (q1, q2, tqCSeqs, tAddCals), "RB", beforeTwoRB, getTwoQubitRBAD(tqCSeqs, tAddCals), tqCSeqs),
                              ("SingleQubitRB_AC", (q1,sqCSeqs, False, tAddCals), "RB", beforeSingleRBAC, getSingleQubitRBAC_AD(sqCSeqs, tAddCals), sqCSeqs),
# Warning: This next one is slow....
                              ("SimultaneousRB_AC", (qr, simCSeqs, tAddCals), "RB", beforeSimRBAC, getSimRBACAD(simCSeqs, tAddCals, qr), simCSeqs),
# This next one relies on a file of sequence strings, which I don't have
#                                          ("SingleQubitIRB_AC", (q1,None), "RB", None, None, None),
# Comment says this next one relies on a specific file, so don't bother running
#                              # ("SingleQubitRBT", (q1,'', fixmePulse, True), "RBT", None, None, None),
                           ]:

        print(f"\nRun {func}...")

        # This is typically setting random seed
        if beforeFunc is not None:
            beforeFunc()

        # Here we know the function is in the current file
        # You could use os.path.dirname(os.path.realpath(__file)) to find files relative to this script,
        # Or os.getcwd() to get files relative to where you ran from. Or always use absolute paths.
        resFunc = compile_function(__file__, func, args)
        # Run the QGL2. Note that the generated function takes no arguments itself
        seq = resFunc()
        if toHW:
            import QGL
            print(f"Compiling {func} sequences to hardware\n")
            # QGL.Compiler.set_log_level()
            em = None
            if cseqs:
                em = {'sequences':cseqs}
            fileNames = qgl2_compile_to_hardware(seq, filename=f'{label}/{label}', axis_descriptor=axisDesc, extra_meta = em)
            print(f"Compiled sequences; metafile = {fileNames}")
            if plotPulses:
                from QGL.PulseSequencePlotter import plot_pulse_files
                # FIXME: As called, this returns a graphical object to display
                plot_pulse_files(fileNames)
        else:
            print(f"\nGenerated {func} sequences:\n")
            from QGL.Scheduler import schedule

            scheduled_seq = schedule(seq)
            from IPython.lib.pretty import pretty
            print(pretty(scheduled_seq))
Beispiel #14
0
        sequences = resFunction()

        # In verbose mode, turn on DEBUG python logging for the QGL Compiler
        if opts.verbose:
            import logging
            from QGL.Compiler import set_log_level
            # Note this acts on QGL.Compiler at DEBUG by default
            # Could specify other levels, loggers
            set_log_level()

        # Now we have a QGL1 list of sequences we can act on

        if opts.tohw:
            print("Compiling sequences to hardware\n")
            fileNames = qgl2_compile_to_hardware(sequences, opts.prefix,
                                                 opts.suffix)
            print(fileNames)
            if opts.showplot:
                plot_pulse_files(fileNames)
        else:
            print("\nGenerated sequences:\n")
            from QGL.Scheduler import schedule

            scheduled_seq = schedule(sequences)
            from IPython.lib.pretty import pretty
            print(pretty(scheduled_seq))

    if opts.verbose:
        print("Memory usage: {} MB".format(process.memory_info().rss //
                                           (1 << 20)))