Source code for qiskit_qm_provider.quam_macros.superconducting.add_basic_macros

# Copyright 2026 Arthur Strauss
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Seed a QuAM machine with standard superconducting gate-level macros.

Author: Arthur Strauss
Date: 2026-07-12
"""

from __future__ import annotations

import warnings
from typing import TYPE_CHECKING, Literal

from quam.core import QuamRoot

if TYPE_CHECKING:
    from qiskit_qm_provider.backend.qm_backend import QMBackend


[docs] def add_basic_macros( backend: QuamRoot | QMBackend, reset_type: Literal["active", "thermalize"] = "thermalize", **reset_macro_kwargs, ): """Populate a QuAM machine with standard superconducting gate-level macros. Canonical location: ``qiskit_qm_provider.quam_macros.superconducting``. Also re-exported from :mod:`qiskit_qm_provider` and :mod:`qiskit_qm_provider.backend.backend_utils` for backward compatibility. Adds ``x``, ``sx``, ``rz``, ``sy``, ``sydg``, ``measure``, ``reset``, ``delay``, ``id``, and ``cz`` macros. These definitions are **tailored to flux-tunable transmon** hardware and assume pulse naming from ``FluxTunableQuam`` / quam-builder (e.g. ``x180``, ``x90``, readout pulses, ``CZGate`` on pairs). Single-qubit macros are imported from ``quam-builder`` when available; otherwise the provider falls back to local copies under :mod:`qiskit_qm_provider.quam_macros.superconducting.single_qubit_macros` (with a :class:`UserWarning`). Pass a :class:`~quam.core.QuamRoot` or a :class:`~qiskit_qm_provider.backend.QMBackend`. When a backend is passed, its Qiskit target is updated after macros are seeded. .. warning:: Only seeds qubits whose ``macros`` dict is empty. Existing macros are left unchanged. Prefer calling this once on a freshly loaded machine. This is a convenience starting point, not a universal hardware definition. Override macros on your own ``QuamRoot`` for other platforms; coordinate with the Quantum Machines team for quam-builder extensions as needed. Args: backend: A :class:`~qiskit_qm_provider.backend.QMBackend` or :class:`~quam.core.QuamRoot` instance. reset_type: Reset macro variant, ``"active"`` or ``"thermalize"``. **reset_macro_kwargs: Extra keyword arguments forwarded to ``ResetMacro`` (alongside ``reset_type``, ``pi_pulse="x180"``, and ``readout_pulse="readout"``). """ try: from quam_builder.architecture.superconducting.custom_gates.single_qubit_gates import ( ResetMacro, VirtualZMacro, MeasureMacro, DelayMacro, IdMacro, ) except ImportError: warnings.warn("Could not import single qubit macros from quam_builder. Using macros from qiskit_qm_provider.quam_macros.superconducting.single_qubit_macros. Please upgrade quam-builder to the latest version.") from qiskit_qm_provider.quam_macros.superconducting.single_qubit_macros import ( ResetMacro, VirtualZMacro, MeasureMacro, DelayMacro, IdMacro, ) from quam.components.macro import PulseMacro from quam_builder.architecture.superconducting.custom_gates.flux_tunable_transmon_pair.two_qubit_gates import ( CZGate, ) from qiskit_qm_provider.backend.qm_backend import QMBackend if not isinstance(backend, (QuamRoot, QMBackend)): raise ValueError("Backend should be a QuamRoot or QMBackend instance") machine = backend.machine if isinstance(backend, QMBackend) else backend pulse_gate_map = { "x": "x180", "sx": "x90", "sy": "y90", "sydg": "-y90", } for qubit in machine.active_qubits: if not qubit.macros: for gate, pulse in pulse_gate_map.items(): qubit.macros[gate] = PulseMacro(pulse=pulse) qubit.macros["rz"] = VirtualZMacro() qubit.macros["measure"] = MeasureMacro(pulse="readout") qubit.macros["reset"] = ResetMacro(reset_type=reset_type, pi_pulse="x180", readout_pulse="readout", **reset_macro_kwargs) qubit.macros["delay"] = DelayMacro() qubit.macros["id"] = IdMacro() for qubit_pair in machine.active_qubit_pairs: if "cz" not in qubit_pair.macros: try: qubit_pair.macros["cz"] = None qubit_pair.macros["cz"] = CZGate( flux_pulse_qubit=qubit_pair.qubit_control.z.operations["const"].get_reference(), ) except ValueError as e: warnings.warn(f"Could not add default two qubit gates. Add it manually if necessary. Error: {e}") if isinstance(backend, QMBackend): backend.update_target()