July 29th, 2024

Integrated Hybrid Support in the Azure Quantum Development Kit

Some quantum computers can do more than execute a static sequence of gates. The most advanced ones can perform mid-circuit measurements, conditionally execute gates, perform real-time classical computations and re-use qubits. If you want to experiment with these state-of-the-art capabilities, we have good news for you. The Azure Quantum Development Kit now supports running hybrid quantum programs on hardware targets. This kind of program combines classical and quantum computations; thus, we refer to them as hybrid quantum programs.

Last year, we released Azure Quantum’s Integrated Hybrid feature, enabling users to develop their hybrid quantum programs using Q# and the QDK. Since then, we have modernized the QDK, but the initial release did not have support for this feature. After months of dedicated development, we are excited to announce that the QDK again has support for implementing hybrid quantum programs!

Not only we have added support for these advanced capabilities, but we have also made significant improvements to the development experience, and users now have:

  • More detailed and comprehensive design-time feedback.
  • Support for a wider range of Q# features when creating hybrid quantum programs.
  • Optimized compilation for running on quantum hardware.
  • Increased execution reliability on programs submitted to run on quantum computers via the Azure Quantum service.

Integrated Hybrid Unlocks New Possibilities

Hybrid quantum computing refers to the process and architecture of a classical computer and a quantum computer working together to solve a problem.  Integrated hybrid quantum computing is a specific kind of architecture that allows classical computations to be performed while qubits are coherent. This capability in combination with mid-circuit measurement enables features like branching based on measurement and real-time integer computations. These features represent a step forward in the use of high-level programming constructs in quantum applications, opening the door to a new generation of hybrid algorithms such as adaptive phase estimation, return-untilsuccess, and some quantum error correction schemes.

At its most basic form, integrated hybrid quantum computing enables you to perform different operations based on the results from a qubit measurement. For example, the following code snippet conditionally applies an X operation to one qubit if the result of the measurement of another qubit is One:

namespace MyQuantumHybridProgram {
    @EntryPoint() 
    operation Main() : Result { 
        use qs = Qubit[2];
        H(qs[0]);
        if MResetZ(qs[0]) == One {
            X(qs[1]);
        }
        return MResetZ(qs[1]);
    }
}

Conditionally applying quantum gates based on measurement results is a feature that can be used for error correction. You can imagine how you can perform syndrome measurement and based on it apply the appropriate corrections.

You can also use other familiar Q# constructs such as loops and even integer computations that are performed while qubits are coherent. For example, the following program keeps track of how many times a measurement resulted in One and returns a Bool representing whether the count is an even number. Moreover, the program also takes advantage of another hybrid quantum computing feature, qubit re-use, which allows us to just use one qubit instead of the five that would be otherwise required. Note that all of this is automatically handled by the Q# compiler.

namespace MyQuantumHybridProgram {
    @EntryPoint()
    operation Main() : Bool {
        use q = Qubit();
        mutable count = 0;
        let limit = 5;
        for _ in 1..limit {
            // Here we take advantage of an integrated
            // hybrid capability, qubit re-use, so we
            // can repeat this logic many times without 
            // having to use a different qubit each time.
            H(q);
            if MResetZ(q) == One {
                set count += 1;
            }
        }
        return count % 2 == 0;
    }
}

The ability to perform different computations, either classical or quantum, opens the door to the development of new innovative algorithms that are inherently hybrid.

Configuring the QDK

You can run hybrid quantum programs both from Visual Studio Code and Python. In both cases, when working with a Q# program, select QIR Adaptive RI as the Q# target profile. This will enable the QDK to provide accurate design-time feedback. Diving into the details of the QIR Adaptive RI profile:

  • QIR stands for Quantum Intermediate Representation, which is the program representation that the Q# compiler produces.
  • Adaptive is the specific QIR profile. Profiles are defined in the QIR specification and represent a coherent subset of functionality that quantum targets support.
  • RI stands for qubit re-use and integer computations respectively, which are extensions to the QIR Adaptive profile.

Currently, Quantinuum is the only provider in Azure Quantum that supports integrated hybrid quantum computing, so make sure you submit your programs to their targets.

The Q# Compiler Guides You

Once you have set up the Q# target profile, the QDK provides design-time feedback about Q# patterns that are not supported by the chosen quantum target. 

Let’s look at an example of the kind of feedback the QDK provides. Consider the following code snippet:

namespace MyHybridQuantumProgram {
    @EntryPoint()
    operation Main() : Int {
        use q = Qubit();
        H(q); 
        let result = MResetZ(q);

        // We use the measurement result to determine
        // the value of variables of different types.
        // We refer to these variables and values as dynamic.
        // Dynamic Bool and Int values are supported by the
        // QIR Adaptive RI profile. 
        let dynamicBool = result == One ? true | false;
        let dynamicInt = result == Zero ? 0 | 1;

        // Dynamic Double values are not supported by the
        // QIR Adaptive RI profile so the following line
        // will result in a compilation error.
        let dynamicDouble = result == Zero ? 0. | 1.;

        // The QIR Adaptive RI profile supports returning
        // dynamic values of type Result, Bool and Int.
        return dynamicInt;
    }
}

In this program, we use a qubit measurement to determine the value of Bool, Int, and Double variables. Since both dynamic Bool and Int values are supported by the QIR Adaptive RI profile, the compiler does not produce any errors in the lines of code where the dynamicBool and dynamicInt variables are bound. However, since dynamic Double values are not supported by this same profile, the compiler produces an error like the following in the line of code where the dynamicDouble variable is bound:

Image QSharpCompilerHelp

This is just one example of how the Q# compiler provides design-time feedback to guide you on what kind of programs integrated hybrid targets can execute. The accuracy and usefulness of the feedback has significantly improved compared to the previous QDK, in which the compiler could not determine whether it was possible to execute a program on a quantum target before its submission. With the latest version of the QDK, programs execute more reliably when submitted to Azure Quantum targets.

The Q# Compiler Optimizes Your Program for Running on Quantum Hardware

Another improvement that we have made is that we heavily optimize classical computations that do not need to be executed during coherence time. For example, in the following code snippet the loop limit calculation is relatively complex. Even though integer computation support makes it possible to perform this calculation while qubits are coherent, the program does not strictly require it. Since computing resources on current quantum computers are limited, the Q# compiler pre-computes anything that it can to reduce the number of computations that the quantum computer needs to perform, no matter the data type. In this program, the compiler computes the value of the limit variable, unrolls the loop and computes the value of angle for each iteration.

namespace MyHybridQuantumProgram {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Math;

    @EntryPoint()
    operation Main() : Result {
        use q = Qubit();
        let seed = 42;
        let limit = ((seed + 10) % 5) * (seed ^ 2);
        for idx in 0 .. limit {
            let angle = IntAsDouble(idx) * PI();
            Rx(angle, q);
        }
        return MResetZ(q);
    }
}

Give It a Try

If you want to experiment with the most advanced capabilities quantum devices currently offer, install the Azure Quantum Development Kit VS Code Extension or install the qsharp Python package, and start implementing your own quantum hybrid programs. You can get inspiration to develop your own hybrid quantum algorithms from our samples and experiments. We are excited to see what you can accomplish!

Author

0 comments

Leave a comment

Feedback