extract_iqm_pulse

extract_iqm_pulse#

Module: iqm.qrisp_iqm

iqm.qrisp_iqm.extract_iqm_pulse(dqa: DynamicQuantumArchitecture, pass_manager: PassManager | str | None = 'default') Callable[[Callable], Callable[..., Circuit | tuple[Any, ...]]]#

Jasp-trace a Qrisp function and compile it to Circuit.

This is the primary entry point for taking a Qrisp quantum function and turning it into an IQM-native circuit without manual transpilation. The decorator:

  1. Traces the function with make_jaspr() to capture all quantum operations (including IQMPulseOperation instances).

  2. Converts the Jasp representation into a Qrisp QuantumCircuit.

  3. Optionally applies transpilation passes via a PassManager (by default, a convert_to_cz pass is applied).

  4. Converts the transpiled circuit to an Circuit using qrisp_to_iqm_converter().

Parameters:
  • dqa (DynamicQuantumArchitecture) – Determines the physical qubit names and available gate loci.

  • pass_manager (PassManager | str | None) –

    Transpilation strategy for the circuit before IQM conversion:

    • "default" — a PassManager containing only convert_to_cz().

    • None — no transpilation; the circuit is converted as-is (useful when it contains only IQMPulseOperation gates).

    • A custom PassManager — full user control over layout, routing, and gate decomposition.

Returns:

A decorator that, when applied to a function, returns a wrapper whose return type is Circuit, or tuple[..., Circuit] when the original function returns values.

If the decorated function has no return value (only builds a circuit as a side effect), the wrapper returns the corresponding IQM Circuit directly.

If the function returns measurement results (e.g., a QuantumVariable or a list of Clbit), the wrapper returns a tuple (*processed_returns, iqm_circuit) where classical bits are replaced by their IQM readout key strings ("cb_0", "cb_1", …).

Raises:

ValueError – If pass_manager is a string other than "default".

Return type:

Callable[[Callable], Callable[…, Circuit | tuple[Any, …]]]

Examples

First, obtain the device DQA via the IQM Backend:

from iqm.qrisp_iqm import IQMBackend

backend = IQMBackend(
    device_instance="garnet",
    token="YOUR_API_TOKEN",
)
dqa = backend.iqm_client.get_dynamic_quantum_architecture()

Circuit without return values (implicit circuit capture):

from qrisp import QuantumVariable, h, cx, measure
from iqm.qrisp_iqm import extract_iqm_pulse

@extract_iqm_pulse(dqa=dqa)
def bell_circuit():
    qv = QuantumVariable(2)
    h(qv[0])
    cx(qv[0], qv[1])
    measure(qv)

iqm_circuit = bell_circuit()          # → iqm.pulse.Circuit
print(iqm_circuit)

Circuit returning a measurement result:

from qrisp import QuantumFloat, h, measure

@extract_iqm_pulse(dqa=dqa)
def random_float():
    qf = QuantumFloat(3)
    h(qf)
    res = measure(qf)
    return res

random_bits, iqm_circuit = random_float()
print(random_bits)                    # → ("cb_0", "cb_1", "cb_2")
print(iqm_circuit)

Pulse-only circuit (no transpilation needed):

from iqm.qrisp_iqm import delay

@extract_iqm_pulse(dqa=dqa, pass_manager=None)
def pulse_delay():
    qv = QuantumVariable(1)
    delay(qv, duration=100e-9)

iqm_circuit = pulse_delay()
# iqm_circuit.instructions contains a single delay operation
print(iqm_circuit.instructions[0].name)  # → "delay"