ScheduleBuilder#
- class iqm.pulse.builder.ScheduleBuilder(op_table, calibration, chip_topology, channels, component_channels)#
Bases:
object
Builds instruction schedules out of quantum circuits or individual quantum operations.
Encapsulates known quantum ops, the calibration information for them, QPU components and their topology, and controller properties.
- Parameters:
op_table (QuantumOpTable) – definitions of known quantum ops
calibration (OpCalibrationDataTree) – calibration data tree for the quantum ops
chip_topology (ChipTopology) – Chip topology derived from the CHAD.
channels (dict[str, ChannelProperties]) – mapping of controller names to the configurations of their channels
component_channels (dict[str, dict[str, str]]) – Mapping from QPU component name to a mapping of
('drive', 'flux', 'readout')
to the name of the control channel responsible for that function of the component.
Module:
iqm.pulse.builder
Methods
Build a playlist from a number of instruction schedules.
Convert a quantum circuit to a TimeBox.
Calibration data for the given quantum operation, implementation and locus.
Control channels that directly affect quantum operations at the given locus.
Drive channel for the given QPU component.
Flux channel for the given QPU component.
Provide an implementation for a quantum operation at a given locus.
Implementation class for the given operation.
Probe line channel for the probe line
component
belongs to.Get virtual feedback channel for feedback to a given AWG from a given probe line.
All virtual feedback signal channels for the given QPU component.
Is there calibration data for the given quantum operation, implementation and locus?
Inject new calibration data, changing
self.calibration
after the ScheduleBuilder initialisation.Resolve a TimeBox.
Convert a TimeBox to a finished instruction schedule, ready for execution.
Temporary helper function, for converting a sequence of TimeBoxes to a Playlist.
Convert a sequence of TimeBoxes to a Playlist.
Check that the calibration data matches the known quantum operations.
Validate a sequence of circuit operations constituting a quantum circuit.
Utility method for applying Block instructions on every channel of the given locus.
- _cache: dict[str, dict[str, dict[tuple[str, ...], GateImplementation]]]#
Cached GateImplementations. The tree has the same structure as OpCalibrationDataTree.
- _channel_to_component: dict[str, str]#
self.component_channels
mapping inverted cached for scheduling algorithm performance. This mapping is used in the scheduling to determine the components to block based on their associated channels. Only blocking channels are included in this mapping, non-blocking channels (e.g. certain virtual channels) do not block their components, just themselves.
- _variable_sample_rates: bool#
the drive and flux channels should always have uniform sampling rates, so this can happen only due to readout channels.
- Type:
Whether the builder has variable sampling rates in its channels. NOTE
- _channel_types#
Cache the probe and non-probe channel names for the scheduling algorithm performance
- _channel_templates: dict[str, ChannelProperties | None]#
Cache representative channel properties for a probe and a non-probe channel for the scheduling algorithm performance.
- inject_calibration(partial_calibration)#
Inject new calibration data, changing
self.calibration
after the ScheduleBuilder initialisation.Invalidates the gate_implementation cache for the affected operations/implementations/loci. Also invalidates the cache for any factorizable gate implementation, if any of its locus components was affected.
- Parameters:
partial_calibration (dict[str, dict[str, dict[tuple[str, ...] | None, dict[str, Any]]]]) – data to be injected. Must have the same structure as
self.calibration
but does not have to contain all operations/implementations/loci/values. Only the parts of the data that are found will be merged intoself.calibration
(including anyNone
values).self._cache
will be invalidated for the found operations/implementations/loci and only if the new calibration data actually differs from the previous.- Return type:
None
- validate_calibration()#
Check that the calibration data matches the known quantum operations.
- Raises:
ValueError – there is something wrong with the calibration data
- Return type:
None
- get_drive_channel(component)#
Drive channel for the given QPU component.
- get_flux_channel(component)#
Flux channel for the given QPU component.
See
get_drive_channel()
.
- get_probe_channel(component)#
Probe line channel for the probe line
component
belongs to.See
get_drive_channel()
.
- get_virtual_feedback_channels(component)#
All virtual feedback signal channels for the given QPU component.
A virtual feedback channel between a source and a destination exists if the station configuration allows it. component can be either the source or the destination of the signal.
- get_virtual_feedback_channel_for(awg_name, feedback_qubit)#
Get virtual feedback channel for feedback to a given AWG from a given probe line.
- Parameters:
- Returns:
The virtual feedback channel name.
- Raises:
ValueError – if the given AWG does not support fast feedback from the given probe line.
- Return type:
- _get_channel_for_component(component, operation)#
Control channel name for the given QPU component and operation.
- has_calibration(op_name, impl_name, locus)#
Is there calibration data for the given quantum operation, implementation and locus?
- get_calibration(op_name, impl_name, locus)#
Calibration data for the given quantum operation, implementation and locus.
- get_control_channels(locus)#
Control channels that directly affect quantum operations at the given locus.
Includes the probe, drive and flux channels of the locus QPU components. Does not include e.g. any neighboring coupler channels, these will have to be added separately in the TimeBox resolution phase.
Will only return channels that are known to exist, i.e. are found in
ScheduleBuilder.channels
.
- wait(locus, duration, *, rounding=False)#
Utility method for applying Block instructions on every channel of the given locus.
The Block instructions guarantee the locus components to idle for the given duration, and cannot e.g. be replaced with e.g. dynamical decoupling sequences. They are treated the same as any other TimeBox contents:
Blocks on different channels remain aligned in time during scheduling.
The actual waiting time on a particular channel may thus be >=
duration
, if the other channels have less non-blocking space on either side.
Note
TODO For now, this method can round
duration
to the nearest value allowed by each channel if requested. This is for the benefit of EXA sweeping over waiting durations. In the future, EXA sweep generation should be responsible for doing the rounding.- Parameters:
locus (Iterable[str]) – locus components that should experience the wait
duration (float) – how long to wait (in seconds)
rounding (bool) – Iff True, for each channel separately,
duration
will be rounded to the nearest value allowed by the granularity of that channel. The Waits will start simultaneously.
- Returns:
box containing
Block
instructions on every control channel oflocus
- Return type:
- get_implementation(op_name, locus, impl_name=None, *, use_priority_order=False, strict_locus=False, priority_calibration=None)#
Provide an implementation for a quantum operation at a given locus.
- Parameters:
op_name (str) – name of the quantum operation
impl_name (str | None) – name of the implementation (
None
means the implementation is chosen automatically using the logic described below)strict_locus (bool) – iff False, for non-symmetric implementations of symmetric ops the locus order may be changed if no calibration data is available for the requested locus order
use_priority_order (bool) – Only has an effect if
impl_name
isNone
. IffFalse
,QuantumOp.get_default_implementation_for_locus()
is used. Otherwise, the first implementation in the priority order that has calibration data forlocus
is chosen. The priority order is as follows: 1. The locus-specific priority defined inQuantumOp.defaults_for_locus[locus]
if any. 2. The global priority order defined inQuantumOp.implementations
.priority_calibration (dict[str, Any] | None) – Calibration data from which to load the calibration instead of the common calibration data in
calibration
. If no calibration is found for the given implementation orpriority_calibration
isNone
, the common calibration is used. Any non-empty values found inpriority_calibration
will be merged to the common calibration. Note: usingpriority_calibration
will prevent saving/loading via the cache.
- Returns:
requested implementation
- Raises:
ValueError – requested implementation could not be provided
- Return type:
- _find_implementation_and_locus(op, impl_name, locus, *, strict_locus=False)#
Find an implementation and locus for the given quantum operation instance compatible with the calibration data.
- Parameters:
op (QuantumOp) – quantum operation
impl_name (str | None) – Name of the implementation.
None
means use the highest-priority implementation for which we have calibration data.strict_locus (bool) – iff False, for non-symmetric implementations of symmetric ops the locus order may be changed to an equivalent one if no calibration data is available for the requested locus order
- Returns:
chosen implementation name, locus
- Raises:
ValueError – requested implementation could not be found
ValueError – requested implementation had no calibration data for this locus
ValueError – no specific implementation was requested, but no known implementation had calibration data for this locus
- Return type:
- _get_implementation(op, impl_name, locus, strict_locus=False, priority_calibration=None)#
Build a factory class for the given quantum operation, implementation and locus.
The GateImplementations are built when they are first requested, and cached for later use.
- Parameters:
op (QuantumOp) – quantum operation
impl_name (str | None) – Name of the implementation.
None
means use the highest-priority implementation for which we have calibration data.strict_locus (bool) – iff False, for non-symmetric implementations of symmetric ops the locus order may be changed if no calibration data is available for the requested locus order
priority_calibration (dict[str, Any] | None) – Calibration data from which to load the calibration instead of the common calibration data. Priority calibration should be either a dict of the type OILCalibrationData, i.e. containing the operation name, implementation name, and locus, or just a dict containing the calibration data for the locus implied by the args op, impl_name and locus.
- Returns:
requested implementation
- Raises:
ValueError – requested implementation could not be provided or had no calibration data for this locus
- Return type:
- get_implementation_class(op_name, impl_name=None)#
Implementation class for the given operation.
- Parameters:
- Returns:
requested implementation class
- Return type:
- validate_quantum_circuit(operations, *, require_measurements=False)#
Validate a sequence of circuit operations constituting a quantum circuit.
- Parameters:
operations (Iterable[CircuitOperation]) – quantum circuit to be validated
require_measurements (bool) – iff True the circuit must include at least one measurement operation
- Raises:
ValueError –
operations
do not constitute a valid quantum circuit- Return type:
None
- circuit_to_timebox(circuit, *, name='', scheduling_algorithm=SchedulingAlgorithm.HARD_BOUNDARY)#
Convert a quantum circuit to a TimeBox.
- Parameters:
circuit (Iterable[CircuitOperation]) – quantum circuit
name (str) – name of the circuit
scheduling_algorithm (SchedulingAlgorithm) – scheduling algorithm to be used in resolving the TimeBoxes.
- Returns:
unresolved TimeBox that implements
circuit
- Return type:
- timeboxes_to_front_padded_playlist(boxes, *, neighborhood=0)#
Temporary helper function, for converting a sequence of TimeBoxes to a Playlist.
Each individual TimeBox in
boxes
is resolved into a Schedule, and then each schedules is front-padded withWait
instructions on each channel such that the resulting Schedules have equal durations. This is required since for now in Station Control the delay before the final measurement is the same for all the Schedules in a Playlist, and we do not wish to lose coherence waiting for the measurement after each Schedule is done.TODO Once Station Control can handle measurements better, this method should be removed, and
timeboxes_to_playlist()
be used instead.- Parameters:
- Returns:
playlist that implements
boxes
, padded schedule duration in seconds- Return type:
- timeboxes_to_playlist(boxes, *, neighborhood=1)#
Convert a sequence of TimeBoxes to a Playlist.
Resolves the boxes, converts them to Schedules, removes unnecessary channels, and then packs the Schedules into a Playlist. Assumes all the TimeBoxes refer to the same QPU and its control channels.
- Parameters:
boxes (Iterable[TimeBox]) – TimeBoxes to include in the playlist
neighborhood (int) – During scheduling, block neighboring channels of the used components this far. The default value ensures that quantum operations work as intended, assuming the station is properly calibrated. Higher values may help defend against crosstalk, at the expense of a longer instruction schedule and thus more decoherence.
- Returns:
playlist that implements
boxes
- Return type:
Playlist
- timebox_to_schedule(box, *, neighborhood=1)#
Convert a TimeBox to a finished instruction schedule, ready for execution.
Resolves the box, then converts the durations of the instructions in the schedule to samples at the channel sample_rate.
- Parameters:
box (TimeBox) – TimeBox to resolve
neighborhood (int) – During scheduling, block neighboring channels of the used components this far. The default value ensures that quantum operations work as intended, assuming the station is properly calibrated. Higher values may help defend against crosstalk, at the expense of a longer instruction schedule and thus more decoherence.
- Returns:
finished schedule that implements
box
- Return type:
- _finish_schedule(schedule)#
Finishes the instruction schedule.
filters out zero-duration Blocks and Waits
converts all spacer instructions used during scheduling to Waits
merges consequent Waits
removes channels that only have Waits in them
This should be the final step of the schedule building process, after this the resulting Schedule can no longer be consistently extended with another (since all the spacer instructions are gone).
- resolve_timebox(box, *, neighborhood, compute_neighborhood_hard_boundary=False)#
Resolve a TimeBox.
Resolves recursively each of the children of the box, and then concatenates the resulting Schedules into a new one using a specific scheduling strategy and algorithm.
The supported algorithms are
HARD_BOUNDARY
, which treats each composite TimeBox as a solid rectangle (the longest channel within defines the duration) andTETRIS
, which packs the schedule as tightly as possible (solid instructions still cannot overlap) regardless of the TimeBox boundaries.Modifies
box
so that it becomes atomic, if it isn’t already.- Parameters:
box (TimeBox) – TimeBox to resolve
neighborhood (int) – During scheduling, block control channels of neighboring QPU components this far from the locus. Values higher than 0 may help defend against crosstalk, at the expense of a longer instruction schedule and thus more decoherence.
compute_neighborhood_hard_boundary (bool) – Whether to precompute the neighborhood components while resolving a composite
TimeBox
in theHARD_BOUNDARY
algorithm. Typically one does not want to do this on the top layer compositeTimeBox
, since it would be unused. The algorithm sets thisTrue
on lower layers, where it improves the performance as the neighborhood components are needed in scheduling.
- Returns:
instruction schedule that implements
box
- Return type:
- _resolve_timebox_hard_boundary(box, neighborhood, compute_neighborhood=False)#
Resolves a TimeBox using the
HARD_BOUNDARY
algorithm, which treats each composite TimeBox as a solid rectangle (the longest channel within defines the duration).
- _get_neighborhood_hard_boundary(box, neighborhood)#
Computes and caches the blocking neighborhoods for HARD_BOUNDARY algorithm.
- _resolve_timebox_tetris(box, *, neighborhood)#
Resolves a TimeBox using the
TETRIS
algorithm, which packs the schedule as tightly as possible (solid instructions still cannot overlap) regardless of the TimeBox boundaries.
- _block_neighborhood_tetris(schedule, locus, neighborhood)#
Add additional blocked channels to the schedule, preventing their use during the schedule.
In the idealized computational model we assume that in a (correctly calibrated) quantum computer there is no effective interaction between QPU components (in the computational frame and subspace) while a
Wait
instruction is acting on the flux channel of the coupler connecting those components (i.e., the coupler is idling). Hence a QPU component experiences no effective evolution if Wait instructions are acting on its drive, flux and probe channels, and the flux channels of all its couplers.Of course, in reality the QPU will experience at least some decoherence during a Wait, and possibly some crosstalk. In some applications, e.g. decoherence experiments, it is essential to Wait for a specific time, since it’s precisely the decoherence that we are interested in.
However, if we are only interested in applying well-defined local quantum operations on specific loci, it is essential to shut down all unwanted dynamics by adding
Block
instructions on control channels of the unused and neighboring channels. They act like Waits (and are converted into Waits at the end of the scheduling), but are allowed to overlap in time, since we are only interested in blocking those channels for the duration of the quantum operation.- Parameters:
schedule (Schedule) – instruction schedule to modify
locus (set[str]) – information-carrying QPU components
schedule
is meant to operate on (does not include couplers)neighborhood (int) – How far should we block neighboring QPU components? Zero means just the locus qubits, one means neighboring couplers, two means their neighboring qubits etc.
- Returns:
schedule
, with addedBlock
instructions on all the neighbor channels, for the duration of the schedule- Return type:
None
- build_playlist(schedules, finish_schedules=True)#
Build a playlist from a number of instruction schedules.
This involves compressing the schedules so that no duplicate information needs to be transferred to Station Control.
All virtual channels are dropped at this point.
- Parameters:
- Returns:
playlist containing the schedules
- Raises:
ValueError – if the schedules contain channels with non-uniform sampling rates
- Return type:
Playlist