Source code for qblox_scheduler.device_under_test.mock_setup

# type: ignore[reportCallIssue] # TODO: Remove after refactoring SchedulerBaseModel.__init__

# Repository: https://gitlab.com/qblox/packages/software/qblox-scheduler
# Licensed according to the LICENSE file on the main branch
#
# Copyright 2020-2025, Quantify Consortium
# Copyright 2025, Qblox B.V.
"""Code to set up a mock setup for use in tutorials and testing."""

from __future__ import annotations

from typing import Any

import numpy as np

from qblox_scheduler.device_under_test.composite_square_edge import (
    CompositeSquareEdge,
)
from qblox_scheduler.device_under_test.nv_element import BasicElectronicNVElement
from qblox_scheduler.device_under_test.quantum_device import QuantumDevice
from qblox_scheduler.device_under_test.transmon_element import BasicTransmonElement
from qblox_scheduler.instrument_coordinator import InstrumentCoordinator
from quantify_core.measurement.control import MeasurementControl


[docs] def set_up_mock_transmon_setup() -> dict: r""" Set up a system containing 5 transmon device elements connected in a star shape. .. code-block:: q0 q1 \ / q2 / \ q3 q4 Returns a dictionary containing the instruments that are instantiated as part of this setup. The keys corresponds to the names of the instruments. """ meas_ctrl = MeasurementControl("meas_ctrl") instrument_coordinator = InstrumentCoordinator( name="instrument_coordinator", add_default_generic_icc=False ) q0 = BasicTransmonElement("q0") q1 = BasicTransmonElement("q1") q2 = BasicTransmonElement("q2") q3 = BasicTransmonElement("q3") q4 = BasicTransmonElement("q4") # Ensure the readout pulse is not replaced by offsets on Qblox backend for testing purposes. q0.measure.pulse_duration = 50e-9 edge_q0_q2 = CompositeSquareEdge(parent_element=q0, child_element=q2) edge_q1_q2 = CompositeSquareEdge(parent_element=q1, child_element=q2) edge_q2_q3 = CompositeSquareEdge(parent_element=q2, child_element=q3) edge_q2_q4 = CompositeSquareEdge(parent_element=q2, child_element=q4) quantum_device = QuantumDevice(name="quantum_device") quantum_device.add_element(q0) quantum_device.add_element(q1) quantum_device.add_element(q2) quantum_device.add_element(q3) quantum_device.add_element(q4) quantum_device.add_edge(edge_q0_q2) quantum_device.add_edge(edge_q1_q2) quantum_device.add_edge(edge_q2_q3) quantum_device.add_edge(edge_q2_q4) quantum_device.instr_instrument_coordinator = instrument_coordinator # Rationale of the dict format is that all instruments can be cleaned up by # iterating over the values and calling close. It also avoids that the instruments # get garbage-collected while their name is still recorded and used to refer to the # instruments. return { "meas_ctrl": meas_ctrl, "instrument_coordinator": instrument_coordinator, "q0": q0, "q1": q1, "q2": q2, "q3": q3, "q4": q4, "q0_q2": edge_q0_q2, "q1_q2": edge_q1_q2, "q2_q3": edge_q2_q3, "q2_q4": edge_q2_q4, "quantum_device": quantum_device, }
[docs] def set_standard_params_transmon(mock_setup: dict) -> None: """ Set somewhat standard parameters to the mock setup generated above. These parameters serve so that the quantum-device is capable of generating a configuration that can be used for compiling schedules. In normal use, unknown parameters are set as 'nan' values, forcing the user to set these. However for testing purposes it can be useful to set some semi-random values. The values here are chosen to reflect typical values as used in practical experiments. """ q0 = mock_setup["q0"] q0.rxy.amp180 = 0.115 q0.rxy.beta = 2.5e-10 q0.clock_freqs.f01 = 7.3e9 q0.clock_freqs.f12 = 7.0e9 q0.clock_freqs.readout = 8.0e9 q0.measure.acq_delay = 100e-9 q0.measure.acq_channel = 0 q1 = mock_setup["q1"] q1.rxy.amp180 = 0.325 q1.rxy.beta = 2.5e-10 q1.clock_freqs.f01 = 7.25e9 q1.clock_freqs.f12 = 6.89e9 q1.clock_freqs.readout = 8.3e9 q1.measure.acq_delay = 100e-9 q1.measure.acq_channel = 1 q2 = mock_setup["q2"] # controlled by a QCM-RF max output amp is 0.25V q2.rxy.amp180 = 0.213 q2.rxy.beta = 2.5e-10 q2.clock_freqs.f01 = 6.33e9 q2.clock_freqs.f12 = 6.09e9 q2.clock_freqs.readout = 8.5e9 q2.measure.acq_delay = 100e-9 q2.measure.acq_channel = 2 q3 = mock_setup["q3"] q3.rxy.amp180 = 0.215 q3.rxy.beta = 2.5e-10 q3.clock_freqs.f01 = 5.71e9 q3.clock_freqs.f12 = 5.48e9 q3.clock_freqs.readout = 8.7e9 q3.measure.acq_delay = 100e-9 q3.measure.acq_channel = 3 q4 = mock_setup["q4"] q4.rxy.amp180 = 0.208 q4.rxy.beta = 2.5e-10 q4.clock_freqs.f01 = 5.68e9 q4.clock_freqs.f12 = 5.41e9 q4.clock_freqs.readout = 9.1e9 q4.measure.acq_delay = 100e-9 q4.measure.acq_channel = 4 for i in range(5): qi: BasicTransmonElement = mock_setup[f"q{i}"] sample_rate = 500 # MHz acq_duration_us = 2 qi.measure.acq_weights_a = np.ones(sample_rate * acq_duration_us) * 0.6 # type: ignore[reportAttributeAccessIssue] qi.measure.acq_weights_b = np.ones(sample_rate * acq_duration_us) * 0.4 # type: ignore[reportAttributeAccessIssue] qi.measure.acq_weights_sampling_rate = sample_rate * 1e6 qi.measure.acq_weight_type = "Numerical"
[docs] def set_up_mock_basic_nv_setup() -> dict: """ Set up a system containing 2 electronic device elements in an NV center. After usage, close all instruments. Returns ------- All instruments created. Containing a "quantum_device", electronic qubit "qe0", "meas_ctrl" and "instrument_coordinator". """ meas_ctrl = MeasurementControl("meas_ctrl") instrument_coordinator = InstrumentCoordinator( name="instrument_coordinator", add_default_generic_icc=False ) qe0 = BasicElectronicNVElement("qe0") qe1 = BasicElectronicNVElement("qe1") quantum_device = QuantumDevice(name="quantum_device") quantum_device.add_element(qe0) quantum_device.add_element(qe1) quantum_device.instr_instrument_coordinator = instrument_coordinator # Rationale of the dict format is that all instruments can be cleaned up by # iterating over the values and calling close. It also avoids that the instruments # get garbage-collected while their name is still recorded and used to refer to the # instruments. return { "meas_ctrl": meas_ctrl, "instrument_coordinator": instrument_coordinator, "qe0": qe0, "qe1": qe1, "quantum_device": quantum_device, }
[docs] def set_standard_params_basic_nv(mock_nv_device: dict[str, Any]) -> None: """ Set somewhat standard parameters to the mock setup generated above. These parameters serve so that the quantum-device is capable of generating a configuration that can be used for compiling schedules. In normal use, unknown parameters are set as 'nan' values, forcing the user to set these. However for testing purposes it can be useful to set some semi-random values. The values here are chosen to reflect typical values as used in practical experiments. All amplitudes for pulses are set to 1e-3. """ quantum_device = mock_nv_device["quantum_device"] qe0: BasicElectronicNVElement = quantum_device.get_element("qe0") qe0.clock_freqs.f01 = 3.592e9 qe0.clock_freqs.spec = 2.2e9 qe0.clock_freqs.ionization = 564e12 qe0.clock_freqs.ge0 = 470.4e12 qe0.clock_freqs.ge1 = 470.4e12 - 5e9 qe0.charge_reset.amplitude = 1e-3 qe0.cr_count.readout_pulse_amplitude = 1e-3 qe0.cr_count.spinpump_pulse_amplitude = 1e-3 qe0.reset.amplitude = 1e-3 qe0.measure.pulse_amplitude = 1e-3 qe0.measure.acq_channel = 0 qe0.spectroscopy_operation.amplitude = 1e-3 qe0.pulse_compensation.max_compensation_amp = 0.1 qe0.pulse_compensation.time_grid = 4e-9 qe0.pulse_compensation.sampling_rate = 1e9 qe0.rxy.amp180 = 0.5 qe1: BasicElectronicNVElement = quantum_device.get_element("qe1") qe1.clock_freqs.f01 = 4.874e9 qe1.clock_freqs.spec = 1.4e9 qe1.clock_freqs.ionization = 420e12 qe1.clock_freqs.ge0 = 470.4e12 qe1.clock_freqs.ge1 = 470.4e12 - 5e9 qe1.charge_reset.amplitude = 1e-3 qe1.cr_count.readout_pulse_amplitude = 1e-3 qe1.cr_count.spinpump_pulse_amplitude = 1e-3 qe1.reset.amplitude = 1e-3 qe1.measure.pulse_amplitude = 1e-3 qe1.measure.acq_channel = 1 qe1.spectroscopy_operation.amplitude = 1e-3 qe1.pulse_compensation.max_compensation_amp = 0.1 qe1.pulse_compensation.time_grid = 4e-9 qe1.pulse_compensation.sampling_rate = 1e9 qe1.rxy.amp180 = 0.5