Skip to content

Invoking Q# callables from Python

Stefan J. Wernli edited this page Jan 22, 2025 · 4 revisions

The qsharp Python package makes it easy to call Q# operations and functions from within Python. Each Q# callable defined through calls to qsharp.eval() or in a Q# project loaded via qsharp.init() is automatically added to the qsharp.code module in Python:

import qsharp

qsharp.eval("""
    operation Superposition() : Result {
        use q = Qubit();
        H(q);
        Std.Diagnostics.DumpMachine();
        MResetZ(q)
    }
    """)

qsharp.code.Superposition()
STATE:
|0⟩: 0.7071+0.0000𝑖
|1⟩: 0.7071+0.0000𝑖
One

The same is true for Q# callables defined in Jupyter notebook using the %%qsharp cell magic:

image

These callables can then be invoked as normal Python functions, which will run them in the Q# simulator just as if they were invoked from within a normal Q# context. Any output produced from calls to Message or diagnostics like DumpMachine will appear as normal and the return from the function marshalled into Python:

image

These callables can also be imported within the Python environment:

image

Passing arguments to Callables

Python literals and variables can be passed directly to Q# callables like any other Python function, and types that support conversion into the equivalent Q# types will work as expected:

image

Using Callables in qsharp.run()

Python wrappers around Q# callables can also be passed to the qsharp.run() function to simulate them across multiple shots. Simply pass the relevant Python callable as the first parameter, the number of shots as the second, and any arguments to the callable as additional arguments to run:

qsharp.eval(
    'operation Foo(nResults : Int) : Result[] { Repeated(Zero, nResults) }'
)
qsharp.run(qsharp.code.Foo, 3, 2)
[[Zero, Zero], [Zero, Zero], [Zero, Zero]]

Resource Estimation with Callables

Callables can also be provided to qsharp.estimate() to trigger the Azure Quantum Resource Estimator. Like with qsharp.run() above, the first parameter can be a Callable from qsharp.code (either explicitly referenced or previously imported). The arguments to the Q# Callable must appear after the estimation parameters and before any named arguments to be picked up as variadic arguments:

qsharp.eval(
    """
    operation Test(nQubits : Int) : Unit {
        use qs = Qubit[nQubits];
        for q in qs {
            T(q);
            M(q);
        }
    }
    """
)
res = qsharp.estimate(qsharp.code.Test, params, 7)

Generating Circuits from Callables

Callables can also be used with qsharp.circuit() to generate a circuit description for the given arguments. These can then be displayed with the circuit widget:

image

Compiling QIR from Callables

Python wrappers around Q# callables can also be used with qsharp.compile() to generate QIR. The QIR compilation will use the provided arguments from Python, making it easier to iterate over different parameters for different compilations. For example, this code uses a Q# operation with a paramter for the number of qubits and passes that as an argument from Python:

qsharp.init(target_profile=qsharp.TargetProfile.Base)
qsharp.eval(
    "operation Program(nQubits : Int) : Result[] { use qs = Qubit[nQubits]; MResetEachZ(qs) }"
)
qir = qsharp.compile(qsharp.code.Program, 5)

Compatibility

If a Python value cannot be converted into the correct Q# type or the wrong number of arguments are provided, an exception is raised:

image

Not all Q# types support conversion from/to Python; if a callable has arguments or return values of these types, invoking the function will trigger a runtime exception:

image

Unsupported interop types include Qubits, structs/user-defined-types, and other callables.

Projects as Modules

When using projects, Q# callables will be with a module hierarchy matching the namespace hierarchy of the project:

image

Resetting loaded Callables

When qsharp.init() is called the current compilation and simulator state is reset, so all callables are removed from the qsharp.code module:

image

Any functions previously imported from qsharp.code are also invalidated:

image