qat.middleend.passes.purr.transform module
- class AcquireSanitisation
Bases:
TransformPass
Sanitises the
Acquire
instruction: the first per pulse channel is split into anAcquire
and aDelay
, and other acquisitions have their delay removed.Acquire
instructions are defined by a “duration” for which they instruct the target to readout. They also contain a “delay” attribute, which instructions the acquisition to start after some given time. This pass separates acqusitions with a delay into two instructions for the first acquire that acts on the channel. For multiple acquisitions on a single channel, the delay is not needed for the following acquisitions, and is set to zero.- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.- Return type:
- class BatchedShots(target_data)
Bases:
TransformPass
Determines how shots should be grouped when the total number exceeds that maximum allowed.
The target machine might have an allowed number of shots that can be executed by a single execution call. To execute a number of shots greater than this value, shots can be batched, with each batch executed by its own “execute” call on the target machine. For example, if the maximum number of shots for a target machine is 2000, but you required 4000 shots, then this could be done as [2000, 2000] shots.
Now consider the more complex scenario where 4001 shots are required. Clearly this can be done in three batches. While it is tempting to do this in batches of [2000, 2000, 1], for some target machines, specification of the number of shots can only be achieved at compilation (as opposed to runtime). Batching as described above would result in us needing to compile two separate programs. Instead, it makes more sense to batch the shots as three lots of 1334 shots, which gives a total of 4002 shots. The extra two shots can just be discarded at run time.
Warning
This pass makes certain assumptions about the IR, including that there is only at most one
Repeat
instruction that contributes to the number of readouts, and there is at most one readout per shot. It will change the number of shots in theRepeat
instruction to the decided batch size, and store the total required shots in the IR, which is less than ideal. It would be nice to save this as an analysis result, but an unfortante side effect of the decoupled nature of the middle- and back-end is that the results manager might not necessarily be passed along.- Parameters:
target_data¶ (
TargetData
) – Target-related information.
- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.
- class DeviceUpdateSanitisation
Bases:
TransformPass
Duplicate DeviceUpdate instructions upsets the device injection mechanism, which causes corruption of the HW model.
In fact, a DeviceInjector is currently 1-1 associated with a DeviceUpdate instruction. When multiple DeviceUpdate instructions (sequentially) inject the same “target”, the first DeviceInjector assigns the (correct) value of the attribute (on the target) to the revert_value. At this point the HW model (or any other target kind) is dirty, and any subsequent DeviceInjector updater would surely assign the (wrong, usually a placeholder Variable) to its revert_value. This results in a corrupt HW model whereby reversion wouldn’t have the desired effect.
This pass is a (lazy) fix, which is to analyse when such cases happen and eliminate duplicate DeviceUpdate instructions that target THE SAME “attribute” on THE SAME “target” with THE SAME variable.
- run(ir, res_mgr, met_mgr, *args, **kwargs)
- class EndOfTaskResetSanitisation
Bases:
TransformPass
Checks for a reset on each active qubit at the end of a task, and adds Reset operations if not found.
After each shot, it is expected that the qubit is returned to its ground state, ready for the next shot. This pass ensures this is the case by checking if the last “active” operation on an qubit is a
Reset
, and if not, adds aReset
to the end of the instruction list. By default, theReset
operation will have the drive channel of a qubit as its target. However, if the drive channel is not an active channel, a different active channel on the qubit will be used its place.Reset
instructions currently sit in a weird place. Their targets are drive channels to match the semantics of other quantum instructions (but are instantiated with a :class:Qubit). However, like measurements, resets are a qubit-level operation. You cannot reset the state of a pulse channel, the state is a property of the qubit! To avoid breaking changes, we’ll just deal with that for now, but hope to do better in the refactored instructions…- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to store the analysis results.
- Return type:
- class EvaluatePulses(ignored_shapes=None, acquire_ignored_shapes=None, eval_function=<function evaluate_shape>)
Bases:
TransformPass
Evaluates the amplitudes of
Pulse
instructions, replacing them with aCustomPulse
and accounting for the scale of the pulse channel.Pulse
instructions are defined by (often many) parameters. With the exception of specific shapes, they cannot be implemented directly on hardware. Instead, we evaluate the waveform at discrete times, and communicate these values to the target. This pass evaluates pulses early in the compilation pipeline.The
CustomPulse
instructions will haveignore_channel_scale=True
.- Parameters:
ignored_shapes¶ (
Optional
[list
[PulseShapeType
]]) – A list of pulse shapes that are not evaluated to a custom pulse, defaults to [PulseShapeType.SQUARE].acquire_ignored_shapes¶ (
Optional
[list
[PulseShapeType
]]) – A list of pulse shapes that are not evaluated to a custom pulse forAcquire
filters, defaults to [].eval_function¶ (
callable
) – Allows a pulse evaluation function to be injected, defaults toevaluate_shape()
.
- evaluate_waveform(inst, ignored_shapes, pulse_lookup)
Evaluates the waveform for a
Pulse
orCustomPulse
, accounting for the pulse channel scale.- Return type:
- hash_pulse(pulse)
Hashs a pulse object.
- Return type:
str
- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions as an instruction builder.- Return type:
- class FreqShiftSanitisation(model)
Bases:
TransformPass
Looks for any active frequency shift pulse channels in the hardware model and adds square pulses for the duration.
Warning
This pass assumes the following, which is achieved via other passes:
Synchronize
instructions have already been lowered toDelay
instructions.Durations are static.
- Parameters:
model¶ (
QuantumHardwareModel
) – The hardware model containing the frequency shift channels.
- static add_freq_shift_to_ir(ir, freq_shift_channels)
Adds frequency shift instructions to the instruction builder.
- Return type:
- get_freq_shift_channels()
Returns all active frequency shift pulse channels found in the hardware model.
- Return type:
dict
[PulseChannel
,Qubit
]
- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The QatIR as an instruction builder.res_mgr¶ (
ResultManager
) – The results manager.
- Return type:
- class InactivePulseChannelSanitisation
Bases:
TransformPass
Removes instructions that act on inactive pulse channels.
Many channels that aren’t actually needed to execute the program contain instructions, mainly
Synchronize
instructions andPhaseShift
instructions which can happen when either of the instructions are applied to qubits. To simplify analysis and optimisations in later passes, it makes sense to filter these out to reduce the overall instruction amount.Note
This pass requires results from the
ActivePulseChannelAnalysis
to be stored in the results manager.- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to store the analysis results.
- Return type:
- class InitialPhaseResetSanitisation
Bases:
TransformPass
Checks if every active pulse channel has a phase reset in the beginning.
Warning
This pass implies that an ActiveChannelAnalysis is performed prior to this pass.
- run(ir, res_mgr, *args, **kwargs)
- class InstructionGranularitySanitisation(model, target_data)
Bases:
TransformPass
Rounds the durations of quantum instructions so they are multiples of the clock cycle.
Only supports quantum instructions with static non-zero durations. Assumes that instructions with a non-zero duration only act on a single pulse channel. The santisiation is done for all instructions simultaneously using numpy for performance.
For
CustomPulse
instructions, the durations are rounded up by padding the pulse with zero amplitude at the end. For other relevant instructions, we round down: this is for compatibility with calibration files that are calibrated using legacy code. However, in the future we might consider changing this to round up for consistency.The Pydantic version of the pass will require the (pydantic equivalent) pass
ActivePulseChannelAnalysis
to have run, with results saved to the results manager to extract pulse channel information.Warning
This pass has the potential to invalidate the timings for sequences of instructions that are time-sensitive. For example, if a pulse has an invalid time, it will round it up to the nearest integer multiple. Furthemore, it will assume that
Acquire
instructions have no delay. This can be forced explicitly using theAcquireSanitisation
pass.- Parameters:
target_data¶ (
TargetData
) – Target-related information.
- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.- Return type:
- sanitise_custom_pulses(instructions)
Sanitises the durations of
CustomPulse
instructions by padding the pulses with zero amplitudes.
- sanitise_quantum_instructions(instructions)
Sanitises the durations quantum instructions with non-zero duration by rounding down to the nearest clock cycle.
- class InstructionLengthSanitisation(target_data)
Bases:
TransformPass
Checks if quantum instructions are too long and splits if necessary.
- Parameters:
duration_limit¶ – The maximum allowed clock cycles per instruction.
Warning
The pass will assume that the durations of instructions are sanitised to the granularity of the pulse channels. If instructions that do not meet the criteria are provided, it might produce incorrect instructions (i.e., instructions that are shorter than the clock cycle). This can be enforced using the
InstructionGranularitySanitisation
pass.- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.
- class IntegratorAcquireSanitisation
Bases:
TransformPass
Changes AcquireMode.INTEGRATOR acquisitions to AcquireMode.RAW.
The legacy echo/RTCS engines expect the acquisition mode to be either RAW or SCOPE. While the actual execution can process INTEGRATOR by treating it as RAW, they are typically santitised the runtime using
EchoEngine.optimize()
. If not done in the new pipelines, it will conflict withPostProcessingSantisiation
, and return the wrong results. The new echo engine supports all acquisition modes, so this is not a problem here.- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.
- class LegacyPhaseOptimisation
Bases:
TransformPass
Iterates through the list of instructions and compresses contiguous
PhaseShift
instructions.- run(ir, res_mgr, met_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to save the analysis results.met_mgr¶ (
MetricsManager
) – The metrics manager to store the number of instructions after optimisation.
- class LoopCount
Bases:
int
- class LowerSyncsToDelays
Bases:
TransformPass
Lowers
Synchronize
instructions toDelay
instructions with static times.Increments through the instruction list, keeping track of the cumulative duration. When
Synchronize
instructions are encountered, it is replaced withDelay
instructions with timings calculated from the cumulative durations.Warning
Any manipulations of the instruction set that will alter the timeline and occur after this pass could invalidate the intention of the
Synchronize
instruction.- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.- Return type:
- class MeasurePhaseResetSanitisation
Bases:
TransformPass
Adds a phase reset before every measure pulse.
- run(ir, *args, **kwargs)
- class PhaseOptimisation
Bases:
TransformPass
Iterates through the list of instructions and compresses contiguous
PhaseShift
instructions. This pass will changePhaseReset
toPhaseSet
instructions.- static merge_phase_instructions(target, phase1, phase2)
- run(ir, res_mgr, met_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to save the analysis results.met_mgr¶ (
MetricsManager
) – The metrics manager to store the number of instructions after optimisation.
- class PostProcessingSanitisation
Bases:
TransformPass
Checks that the
PostProcessing
instructions that follow an acquisition are suitable for the acquisition mode, and removes them if not.Extracted from
qat.purr.backends.live.LiveDeviceEngine.optimize()
.- run(ir, _, met_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.met_mgr¶ (
MetricsManager
) – The metrics manager to store the number of instructions after optimisation.
- class QiskitInstructionsWrapper
Bases:
TransformPass
Wraps the Qiskit builder in a wrapper to match the pipelines API.
A really silly pass needed to wrap the
QiskitBuilder
in an object that allows QiskitBuilderWrapper.instructions to be called, allowing the builder to be used in the theLegacyRuntime
. This is needed because the qiskit engine has a different API to other purr engines, requiring the whole builder to be passed (as opposed to builder.instructions).- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
QiskitBuilder
) – The Qiskit instructions- Return type:
- class RepeatSanitisation(model, target_data)
Bases:
TransformPass
Adds repeat counts and repetition periods to
Repeat
instructions. If none is found, a repeat instruction is added.- Parameters:
model¶ (
QuantumHardwareModel
) – The hardware model contains the default repeat value, defaults to None.target_data¶ (
TargetData
) – Target-related information.
- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.
- class RepeatTranslation(target_data)
Bases:
TransformPass
Transform
Repeat
instructions so that they are replaced with:Variable
,Assign
, andLabel
instructions at the start, andAssign
andJump
instructions at the end.- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.- Return type:
- class ResetsToDelays(target_data)
Bases:
TransformPass
Transforms
Reset
operations to :class:`Delay`s.Note that the delays do not necessarily agree with the granularity of the underlying target machine. This can be enforced using the
InstructionGranularitySanitisation
pass.- Parameters:
target_data¶ (
TargetData
) – Target-related information.
- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to store the analysis results.
- Return type:
- class ReturnSanitisation
Bases:
TransformPass
Squashes all
Return
instructions into a single one. Adds aReturn
with all acquisitions if none is found.- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.
- class ScopeSanitisation
Bases:
TransformPass
Bubbles up all sweeps and repeats to the beginning of the list and adds delimiter instructions to the repeats and sweeps signifying the end of their scopes.
Warning
This pass is intended for use with legacy builders that do not use
EndRepeat
andEndSweep
instructions. It will add a delimiter instruction for eachRepeat
andSweep
found in the IR.- run(ir, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.
- class SquashDelaysOptimisation
Bases:
TransformPass
Looks for consecutive
Delay
instructions on a pulse channel and squashes them into a single instruction.Because
Synchronize
instructions across multiple pulse channels are used so frequently to ensure pulses play at the correct timings, it means we can have sequences of many delays. Reducing the number of delays will simplify timing analysis later in the compilation.Delay
instructions commute with phase related instructions, so the only instructions that separate delays in a meaningful way are:Pulse
:,CustomPulse
andAcquire
instructions. We also need to be careful to not squash delays that contain a variable time.- run(ir, res_mgr, met_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to save the analysis results.met_mgr¶ (
MetricsManager
) – The metrics manager to store the number of instructions after optimisation.
- class SynchronizeTask
Bases:
TransformPass
Synchronizes all active pulse channels in a task.
Adds a synchronize to the end of the instruction list for all active pulse channels, which is extracted from the
ActivePulseChannelAnalysis
pass. This is useful to do before resetting the qubits, as it ensures no qubit is reset while the task is still “active”, reducing the effects of cross-talk.- run(ir, res_mgr, *args, **kwargs)
- Parameters:
ir¶ (
InstructionBuilder
) – The list of instructions stored in anInstructionBuilder
.res_mgr¶ (
ResultManager
) – The result manager to store the analysis results.
- Return type: