qat.ir.instruction_builder module
Instruction builder abstractions and a concrete quantum builder.
This module defines the abstract InstructionBuilder API and a
concrete QuantumInstructionBuilder which implements pulse-level gate
construction and measurement helpers. The builders produce an IR
InstructionBlock suitable for later compilation and scheduling stages.
- class InstructionBuilder(hardware_model, instructions=None, _qubit_index_by_uuid=None, _qubits_ordered_by_index=None)
Bases:
ABCAbstract class for assembling quantum programs.
Provides a number of methods to deal with common quantum semantics, such as qubits, gates, measurements, and control flow. The details of how quantum operations are implemented are left to child classes.
- abstract ECR(control, target)
- Return type:
- S(target)
- Return type:
- SX(target)
- Return type:
- SXdg(target)
- Return type:
- Sdg(target)
- Return type:
- T(target)
- Return type:
- Tdg(target)
- Return type:
- abstract U(target, theta, phi, lamb, pulse_channel=None)
- Return type:
- abstract X(target, theta=3.141592653589793, pulse_channel=None)
- Return type:
- abstract Y(target, theta=3.141592653589793, pulse_channel=None)
- Return type:
- abstract Z(target, theta=3.141592653589793, pulse_channel=None)
- Return type:
- add(*instructions, flatten=False)
Add one or more instruction(s) into this builder.
All methods should use this instead of accessing the instructions tree directly as it deals with composite instructions.
- Return type:
- assign(name, value)
- Return type:
- cX(controllers, target, theta=3.141592653589793)
- Return type:
- cY(controllers, target, theta=3.141592653589793)
- Return type:
- cZ(controllers, target, theta=3.141592653589793)
- Return type:
- abstract ccnot(controllers, target)
- Return type:
- cnot(control, target)
- Return type:
- static constrain(angle)
Constrain the rotation angle to avoid redundant rotations around the Bloch sphere.
- abstract controlled(controllers, builder)
- Return type:
- cswap(controllers, target, destination)
- Return type:
- flatten()
Flatten the instruction builder by removing nested structures like InstructionBlocks.
- get_logical_qubit(index)
Returns the qubit assigned with the given logical index.
- get_physical_qubit(index)
Returns the qubit assigned with the given physical index.
- had(target)
- Return type:
- property instructions
- jump(label, condition=None)
- Return type:
- abstract measure_with_granular_post_processing(target, axis=SEQUENCE, output_variable=None)
Measure a qubit and emit the full granular post-processing pipeline.
Compiler frontends should call this method when lowering a measurement assignment into IR. The granular discrimination chain is emitted for both qubits with
post_process_methodconfigured and legacy qubits. For configured qubits, the chain (for exampleEqualise→Discriminate) is derived from the configured post-processing method; for legacy qubits, the equivalent granular chain is derived from legacymean_z_map_argsdata.See
QuantumInstructionBuilder.measure_with_granular_post_processing()for full detail.
- property number_of_instructions
- repeat(repeat_count)
- Return type:
- abstract reset(targets, **kwargs)
- Return type:
- results_processing(variable, res_format)
- Return type:
- returns(variables=None)
Add return statement.
- Return type:
- abstract swap(target, destination)
- Return type:
- PydQuantumInstructionBuilder
alias of
QuantumInstructionBuilder
- class QuantumInstructionBuilder(*args, **kwargs)
Bases:
InstructionBuilderA pulse-level instruction builder, that provides implementations of quantum gates, and an API for pulse-level instructions.
- ECR(control, target)
- Return type:
- U(target, theta, phi, lamb, pulse_channel=None)
Adds an arbitrary rotation around the Bloch sphere with 3 Euler angles to the builder (see https://doi.org/10.48550/arXiv.1707.03429).
- X(target, theta=3.141592653589793, *args, **kwargs)
- Y(target, theta=3.141592653589793, *args, **kwargs)
- Z(target, theta=3.141592653589793, *args, **kwargs)
- ZX(target1, target2, theta=0.7853981633974483)
Adds a two-qubit interaction gate exp(-i heta Z x X) to the builder.
- acquire(target, delay=1e-06, output_variable=None, **kwargs)
- Return type:
- static build_equalise_discriminate_instrs(qubit, output_variable)
Build the
Equalise → Discriminateinstruction pair for any qubit type.This is the single authoritative implementation of the three-way dispatch used by both
emit_granular_post_processing()andInsertPreSelectionMeasurement. Both pre-selection and circuit-measurement paths produce identical pairs for the same qubit, differing only in thePostSelect.additional_disallowedthat follows.Dispatch:
MaxLikelihoodMethod— optionalEqualise(whentransformandoffsetare set) +Discriminatewith the full ML method.LinearMapToRealMethodor legacymean_z_map_args—Equalise(rotation/offset frombuild_legacy_equalise_args()) + thresholdDiscriminate.
- Parameters:
- Return type:
list[Equalise|Discriminate]- Returns:
List of
[Equalise, Discriminate](or[Discriminate]for ML without a pre-rotation).
- static build_legacy_equalise_args(mean_z_map_args)
Compute
Equaliseparameters and discrimination threshold frommean_z_map_args.Given
mean_z_map_args = [A, B]where the legacy linear map isz = Re(A * iq + B), the affine transform applied to the IQ vector[I, Q]is:[I', Q'] = [[a, -b], [b, a]] @ [I, Q] + [c_I, c_Q]
where
a + jb = Aandc_I + jc_Q = B. This is identical to the transform used by theLinearMapToRealMethodbranch ofemit_granular_post_processing().The discrimination threshold is
0.0— the midpoint on the real axis between the rotated state centroids — matching the convention ofDiscriminate(> 0 → "0",≤ 0 → "1").- Parameters:
mean_z_map_args¶ (
list) – Two-element list[A, B]as stored on the legacy qubit.- Return type:
tuple[ndarray,ndarray,float]- Returns:
(transform, offset, threshold)tuple.
- ccnot(controllers, target)
- Return type:
- cnot(control, target)
- Return type:
- controlled(controllers, builder)
- Return type:
- create_pulse_channel(frequency, physical_channel, imbalance=1.0, phase_iq_offset=0.0, scale=1 + 0j, uuid=None)
Creates a pulse channel and adds stores it within the builder.
The channel can be provided as a physical channel which the logical channel is linked too, or use the physical channel of a provided pulse channel.
- Return type:
- delay(target, duration)
- Return type:
- emit_granular_post_processing(target, output_variable)
Emit the granular post-processing instruction chain (without PostSelect).
Emits
Equalise→Discriminatebased on the qubit’s configuration.Discriminateoutputs integer state keys directly. Useemit_post_select()separately to append aPostSelectwhen disallowed states are configured.Dispatches as follows:
LinearMapToRealMethod→Equalise+Discriminate(threshold path; above-threshold → key0, below → key1).MaxLikelihoodMethod→ optionalEqualise+Discriminate(ML path; emits dict keys directly).Legacy (
post_process_method is None,mean_z_map_argsset) →Equalise(rotation derived frommean_z_map_args) +Discriminate.
Integer key convention
Discriminateemits the integer dict key fromstatesfor ML paths, or0/1for threshold/legacy paths. Non-negative keys are allowed states written to the classical register; negative keys are disallowed and subsequently filtered byPostSelect.Results Format Semantics with Compiler Config
Integer output values from
Discriminateflow through the runtime pipeline whereresults_formatflags determine final encoding:``raw()``: Complex IQ arrays from
EqualiseResult(post-mask applied). For legacy acquires without anEqualisestep, falls back to the mapped arrays.``binary()``: Per-shot int output-value array from
Discriminate(one value per retained shot, e.g.[0, 1, 0, ...]). With post-selection, only retained shots are included.``binary_count()``: Dictionary of state string → count using
label_count()on the integer keys fromDiscriminateResult. Key difference: when post-selection is active, the repeat count passed tobinary_count()isshots_retained(notshots_requested), so counts reflect only the passing shots.
Example: 3-state ML with state keyed as -2 (disallowed)
Setup:
states = { 0: MLDiscriminateParams(location=1+0j), 1: MLDiscriminateParams(location=-1+0j), -2: MLDiscriminateParams(location=0+1j), # negative key = disallowed } # 10 shots: 4 → key 0, 3 → key 1, 3 → key -2 (filtered by post-select)
After
Discriminate:[0, 0, 0, 0, 1, 1, 1, -2, -2, -2]
After
PostSelect+ global mask (7 retained):[0, 0, 0, 0, 1, 1, 1]
Format outcomes:
raw(): <complex IQ from EqualiseResult, 7 retained shots> binary(): [0, 0, 0, 0, 1, 1, 1] binary_count(): {"0": 4, "1": 3} (from 7 retained, not 10 requested)
Default Behavior
When
CompilerConfig.results_formatis not set, it defaults toResultsFormatting.DynamicStructureReturn, which simplifies output (removes generated variable names, unwraps single-value results).- Parameters:
- Return type:
- Returns:
The builder instance.
- emit_post_select(output_variable)
Emit a PostSelect instruction after the Discriminate for the given variable.
PostSelectfilters shots whose integer state key is negative. When all keys are non-negative (e.g.LinearMapToRealMethodalways produces0or1) the instruction becomes a no-op at runtime (the validity mask is allTrue). Callers do not need to guard on whether the method has disallowed states.- Parameters:
output_variable¶ (
str) – The variable name to attach to the instruction.- Return type:
- Returns:
The builder instance.
- frequency_shift(target, frequency)
- Return type:
- get_pulse_channel(id)
Given an id, return the corresponding pulse channel.
Checks internally stored pulse channels, but can pull pulse channels from the hardware model if not found.
- Return type:
- measure(targets, mode=INTEGRATOR, output_variable=None, sync_qubits=True)
Measure one or more qubits.
- Parameters:
- Return type:
- measure_mean_signal(target, output_variable=None)
Measure the raw IQ signal of a single qubit and return the shot-averaged result.
Emits a
MeasureBlockusingINTEGRATORacquisition and appends aPostProcessing(MEAN, SEQUENCE)to average the complex IQ values across all shots. Results are a single complex value per qubit.
- measure_mean_z(target, axis=SEQUENCE, output_variable=None)
Measure a single qubit along the z-axis and return the shot-averaged result.
Emits a
MeasureBlock, averages first over the time axis (SCOPE mode only) then over the sequence axis (INTEGRATOR mode only), and finally emitsPostProcessing(LINEAR_MAP_COMPLEX_TO_REAL)to project the averaged complex IQ value to a real z-expectation value.Note
Like
measure_single_shot_z(), this method always emits a legacyPostProcessinginstruction. Usemeasure_with_granular_post_processing()for the granular discrimination pipeline.- Parameters:
axis¶ (
ProcessAxis) – The axis along which post-processing of readouts should occur.output_variable¶ (
Optional[str]) – Name of the variable where the acquire result is saved. A unique name is generated if not provided.
- Returns:
The builder instance.
- measure_scope_mode(target, output_variable=None)
Measure the qubit in scope (waveform-capture) mode.
Emits a
MeasureBlockusingSCOPEacquisition mode. No post-processing is applied; the raw time-series IQ waveform is stored directly in the output variable.
- measure_single_shot_binned(target, axis=SEQUENCE, output_variable=None)
Measure a single qubit along the z-axis and discriminate to ±1 (customer-facing API).
Emits a
MeasureBlock, an optionalPostProcessing(MEAN, TIME)(SCOPE mode only),PostProcessing(LINEAR_MAP_COMPLEX_TO_REAL)to project complex IQ to a real z-value, and aPostProcessing(DISCRIMINATE)that rounds the z-projection value to +1 (above threshold) or −1 (at or below threshold).Note
This method uses the legacy
DISCRIMINATEpost-processing type and does not emit the granularDiscriminateinstruction used by the post-selection pipeline. It is not equivalent tomeasure_with_granular_post_processing()(which usesDiscriminate/PostSelect) and should not be substituted for it.- Parameters:
axis¶ (
ProcessAxis) – The axis along which post-processing of readouts should occur.output_variable¶ (
Optional[str]) – Name of the variable where the acquire result is saved. A unique name is generated if not provided.
- Returns:
The builder instance.
- measure_single_shot_signal(target, axis=SEQUENCE, output_variable=None)
Measure the raw IQ signal of a single qubit (customer-facing API).
Emits a
MeasureBlockand, whenaxisisTIME(SCOPE mode), an additionalPostProcessing(MEAN, TIME)to average over the time axis. No z-discrimination is applied; results are an ndarray of complex IQ values, one per shot.- Parameters:
axis¶ (
ProcessAxis) – The axis along which post-processing of readouts should occur.output_variable¶ (
Optional[str]) – Name of the variable where the acquire result is saved. A unique name is generated if not provided.
- Returns:
The builder instance.
- measure_single_shot_z(target, axis=SEQUENCE, output_variable=None)
Measure a single qubit along the z-axis (customer-facing API).
Emits a
MeasureBlock, an optionalPostProcessing(MEAN, TIME)whenaxisisTIME(SCOPE mode), and aPostProcessing(LINEAR_MAP_COMPLEX_TO_REAL)to project the complex IQ value onto a real z-projection. Results are an ndarray of floats centred around 0: values above 0 indicate a bias towards the +Z state, values below 0 indicate a bias towards the −Z state.Note
This method always emits a legacy
PostProcessinginstruction regardless of whetherpost_process_methodis configured on the qubit. Compiler frontends that need the granular discrimination pipeline (Equalise→Discriminate→PostSelect) should callmeasure_with_granular_post_processing()instead (andemit_post_select()for post-selection insertion).- Parameters:
axis¶ (
ProcessAxis) – The axis along which post-processing of readouts should occur.SEQUENCE(default) usesINTEGRATORacquisition;TIMEusesSCOPEacquisition and emits an additionalPostProcessing(MEAN, TIME).output_variable¶ (
Optional[str]) – Name of the variable where the acquire result is saved. A unique name is generated if not provided.
- Returns:
The builder instance.
- measure_with_granular_post_processing(target, axis=SEQUENCE, output_variable=None)
Measure a qubit and emit the full granular post-processing pipeline.
This method is intended for use by compiler frontends (QASM2, QASM3, QIR, tket) where the result of a measurement assignment must be discriminated into state labels. Customer-facing code that only needs raw z-projection floats should call
measure_single_shot_z()instead.For qubits with a
post_process_methodconfigured the emitted sequence is:MeasureBlock(viameasure())Optional
PostProcessing(MEAN, TIME)via_take_time_mean()(only for SCOPE / TIME axis).The granular chain from
emit_granular_post_processing():Equalise→Discriminate.
Frontends that need post-selection should append
emit_post_select()explicitly based on compiler configuration.For legacy qubits (
post_process_method is None,mean_z_map_argsset),emit_granular_post_processing()derives theEqualiserotation frommean_z_map_argsand emits the sameEqualise→Discriminatechain so that all measurement paths use one unified pipeline.- Parameters:
axis¶ (
ProcessAxis) – The axis along which post-processing of readouts should occur.output_variable¶ (
Optional[str]) – The variable where the acquire result will be saved. A unique name is generated if not provided.
- Return type:
- Returns:
The builder instance.
- phase_shift(target, theta=3.141592653589793, *args, **kwargs)
- post_processing(target, output_variable, process_type, axes=None, args=None)
Emit a legacy
PostProcessinginstruction.Populates
argsautomatically when none are provided:LINEAR_MAP_COMPLEX_TO_REAL— reads fromtarget.mean_z_map_args(legacy) ortarget.post_process_method.mean_z_map_args(new-styleLinearMapToRealMethod).DISCRIMINATE— reads fromtarget.discriminator.
- Parameters:
target¶ (
Qubit) – The qubit whose calibration data is used to fillargs.output_variable¶ (
str) – The variable name to attach to the instruction.process_type¶ (
PostProcessType) – The type of post-processing to apply.axes¶ (
Union[ProcessAxis,list[ProcessAxis],None]) – Axis or axes along which the post-processing operates.args¶ – Explicit arguments for the post-processing; auto-filled when
NoneforLINEAR_MAP_COMPLEX_TO_REALandDISCRIMINATEtypes.
- Return type:
- Returns:
The builder instance.
- pretty_print()
- Return type:
str
- pulse(**kwargs)
- Return type:
- reset(targets, **kwargs)
- Return type:
- swap(target, destination)
- Return type:
- synchronize(targets)
- Return type: