Source code for qblox_scheduler.segments.loops
# Repository: https://gitlab.com/qblox/packages/software/qblox-scheduler
# Licensed according to the LICENSE file on the main branch
#
# Copyright 2025, Qblox B.V.
"""Module containing the segment to a set a parameter."""
from __future__ import annotations
from typing import TYPE_CHECKING
from tqdm.autonotebook import trange
from qblox_scheduler.analysis.helpers import concat_acq_data
from qblox_scheduler.operations.loop_domains import unpack_complex_variables
from qblox_scheduler.segments.segment import Segment
if TYPE_CHECKING:
from xarray import Dataset
from qblox_scheduler.device_under_test import QuantumDevice
from qblox_scheduler.operations.expressions import Expression
from qblox_scheduler.operations.loop_domains import LinearDomain
from qblox_scheduler.operations.variables import Variable
from qblox_scheduler.schedules.schedule import TimeableScheduleBase
[docs]
class Loop(Segment):
"""Experiment segment that loops other segments over some values."""
def __init__(self, domains: dict[Variable, LinearDomain], segments: list[Segment]) -> None:
super().__init__(f"loop segments over {domains}")
self.data["loop_info"] = {
"domains": domains,
"segments": segments,
}
@property
[docs]
def domains(self) -> dict[Variable, LinearDomain]:
"""Domains to loop over."""
return self.data["loop_info"]["domains"]
@property
[docs]
def segments(self) -> list[Segment]:
"""Segments to execute."""
return self.data["loop_info"]["segments"]
[docs]
def run(self, device: QuantumDevice, timeout: int = 10) -> Dataset | None:
"""Execute segment on quantum device."""
if not self.domains:
return
domains = unpack_complex_variables(self.domains)
data_set = None
nsteps = len(next(iter(domains.values())))
values = {var: iter(dom.values()) for var, dom in domains.items()}
for _ in trange(nsteps, unit="step"):
substitutions: dict[Expression, Expression | int | float | complex] = {
var: next(values) for var, values in values.items()
}
for segment in self.segments:
sub_segment = segment.substitute(substitutions)
sub_data_set = sub_segment.run(device, timeout=timeout)
if sub_data_set is not None:
if data_set is None:
data_set = sub_data_set
else:
data_set = concat_acq_data([data_set, sub_data_set])
return data_set
[docs]
def _unrolled_segments(self) -> list[TimeableScheduleBase | Segment]:
if not self.domains:
return []
timeable_schedule_segments = []
domains = unpack_complex_variables(self.domains)
nsteps = len(next(iter(domains.values())))
values = {var: iter(dom.values()) for var, dom in domains.items()}
for _ in range(nsteps):
substitutions: dict[Expression, Expression | int | float | complex] = {
var: next(values) for var, values in values.items()
}
for segment in self.segments:
substituted_segment = segment.substitute(substitutions)
timeable_schedule_segments += substituted_segment._unrolled_segments()
return timeable_schedule_segments