Skip to content

bloqade.gemini.decoding.experiments.PostSelectionExperiment

← Module overview

classPostSelectionExperimentsource

bloqade.gemini.decoding.experiments.PostSelectionExperiment

A "wizard" class that orchestrates the steps of running a experiment to do tomography which obtains samples from the hardware and runs decoding with postselection on your ancilla qubits.

Signature
class PostSelectionExperiment(nonclifford_prefix: ir.Method[..., None], clifford_circuit: ir.Method[..., None], tomography_circuits: Mapping[str, ir.Method[..., None]], decoder: type[ConfidenceDecoder], decoder_init_args: Mapping[str, object] | None = None)

It defines methods for creating noisy tomography circuits, creating decoders from the detector error models from those tomography circuits, sampling from the hardware, and doing some analysis based on the confidence associated with each shot.

Parameters

NameTypeDefaultDescription
nonclifford_prefixir.Method[..., None]required
clifford_circuitir.Method[..., None]required
tomography_circuitsMapping[str, ir.Method[..., None]]required
decodertype[ConfidenceDecoder]required
decoder_init_argsMapping[str, object] | NoneNone

Attributes

NameTypeDescription
nonclifford_prefixir.Method[..., None]A SQuIN kernel consisting of a single layer of single-qubit gates applied to the physical qubits before the state-preparation circuit is applied.
clifford_circuitir.Method[..., None]A SQuIN kernel consisting of a Clifford circuit applied to the logical qubits (after logical encoding).
tomography_circuitsir.Method[..., None]A mapping of basis strings to SQuIN kernels consisting of a clifford circuit applied to your logical qubits.
Thesekernels will be appended to your circuits in the following fashion, for each `basis_label in tomography_circuits``nonclifford_prefix + clifford_circuit + tomography_circuits[basis_label]` From these circuits in each basis, a DEM will be extracted to initialize decoders in each basis.
decodertype[ConfidenceDecoder]A type of ConfidenceDecoder used to initialize decoders.
decoder_init_argsMapping[str, object] | NoneOptional arguments that can be passed in to initialize the decoder. Defaults to None.

methodkernelssource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.kernels

Signature
def kernels(num_logical_qubits: int = 5) -> dict[str, ir.Method[..., _LogicalTomographyReturn]]

Composes the nonclifford, clifford, and tomography kernels into a dictionary mapping each basis label to the respective nonclifford + clifford + tomography kernel.

Parameters

NameTypeDefaultDescription
num_logical_qubitsint5An integer corresponding to the number of logical qubits allocated in the kernels.

Returns

dict[str, ir.Method[..., _LogicalTomographyReturn]]A dictionary mapping the tomography basis labels to the respective kernel used for tomography.

source

methoddem_circuitssource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.dem_circuits

def dem_circuits() -> dict[str, tsim_backend.Circuit]

Constructs TSIM circuits annotated with error channels for each basis from the tomography kernels, which will later be used to construct detector error models.

Note: this function depends on .kernels() being invoked. Note: in the implementation of this function, to obtain a noiseless reference observable to later construct a DEM, we take our whole circuit, strip away the noise, and prepend it to our circuit so that the noiseless behavior is U^dagU = I.

Returns

(dict[str, tsim_backend.Circuit], dict[str, tsim_backend.Circuit])A dictionary mapping each basis label to a compiled TSIM circuit with noise channels, where the observables in noiseless simulation are all 0.

source

methoddemssource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.dems

def dems() -> dict[str, stim.DetectorErrorModel]

Constructs detector error models from the noisy circuits in each basis. Defaults to approximating disjoint errors.

Note: this function depends on dem_circuits() being called.

Returns

(dict[str, stim.DetectorErrorModel], dict[str, stim.DetectorErrorModel])A dictionary mapping each basis label to the detector error model for the tomography circuit in that basis.

source

methodinitialize_decoderssource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.initialize_decoders

Signature
def initialize_decoders() -> dict[str, tuple[ConfidenceDecoder, BaseDecoder]]

Initializes the decoders for the tomography circuits in each basis from the detector error models. This function utilizes correlated decoding (https://arxiv.org/abs/2403.03272). Because of this, this function initializes two decoders: one for the decoding the ancilla qubits, and one for decoding the output qubit. The decoder that decodes the ancilla qubits decodes them jointly, taking in (num_ancillas * 3) detectors and outputting corrections for (num_ancillas) observables. This decoder does not additionally take in the output qubit’s detectors for the case that the output qubit might be used later in the computation. The decoder that decodes the output qubit decodes it jointly with the ancilla qubits, taking in ((num_ancillas + 1) * 3) detectors and outputting corrections for 1 observable (on the output qubit). This function assumes that the first qubit is the output qubit, and also assumes that we are using the [[7, 1, 3]] Steane code, which has three detectors per logical qubit.

Note: this function depends on dems() being called.

Returns

(dict[str, tuple[ConfidenceDecoder, BaseDecoder]], dict[str, tuple[ConfidenceDecoder, BaseDecoder]])A dictionary mapping each basis label to (factory_decoder, full_decoder), where factory_decoder decodes the ancilla qubits jointly and full_decoder decodes the output qubit jointly with the information on all logical qubits.

source

methodmake_taskssource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.make_tasks

Signature
def make_tasks(device: GeminiLogicalSimulator) -> dict[str, GeminiLogicalSimulatorTask[_LogicalTomographyReturn]]

Prepares tasks for submission to the hardware device.

Parameters

NameTypeDescription
deviceGeminiLogicalSimulator

Returns

dict[str, GeminiLogicalSimulatorTask[_LogicalTomographyReturn]]

source

methodget_samplessource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.get_samples

def get_samples(num_shots: int) -> dict[str, _BasisDataset]

For each basis, samples num_shots from the hardware. Returns the detector and observable information for each task.

Parameters

NameTypeDescription
num_shotsint

Returns

dict[str, _BasisDataset]

source

methoddecode_and_postselectsource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.decode_and_postselect

Signature
def decode_and_postselect(postselection_condition: np.ndarray, progress_label: str | bool = False) -> dict[str, _DecodedPostselectionResult]

With the resulting shot data from the hardware samples, runs the following steps:

  1. Decoding and correction on the ancilla qubits
  2. Filtering shots whose corrected ancilla observable is a valid pattern in postselection_condition
  3. Out of these filtered shots, decode and correct the output qubit
  4. Returns the corrected observables as well as the confidence score associated with each observable.

Parameters

NameTypeDefaultDescription
postselection_conditionnp.ndarrayrequiredA 2D numpy array of shape (num_conditions, num_ancillae) representing the valid ancilla patterns to postselect on. Example: If postselection_condition = np.array([[1, 0, 1, 1]]), then we will only accept shots where the first ancilla is 1, the second ancilla is 0, the third ancilla is 1, and the fourth ancilla is 1 after those ancilla have been corrected by the decoder.
progress_labelstr | boolFalseIf False, no progress bar is displayed. If True, the decoder class name is used as the progress-bar label. If a string, that string is used as the progress-bar label. Defaults to False.

Returns

dict[str, _DecodedPostselectionResult]A dictionary that maps each basis to postselected observables and confidence scores per shot.

source

methodanalysis_f_vs_fractionsource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.analysis_f_vs_fraction

Signature
def analysis_f_vs_fraction(*, target_bloch: np.ndarray = _DEFAULT_TARGET_BLOCH, threshold_points: int = 64, min_accepted_per_basis: int = 50) -> PostselectionCurveData

Analyzes the shot data to produce arrays for the fidelity to some target state as a function of the fraction of total accepted shots. Produces various thresholds of accepted shots by thresholding on the confidence score associated with each shot.

Parameters

NameTypeDefaultDescription
target_blochnp.ndarray_DEFAULT_TARGET_BLOCHThe bloch vector to which fidelity is computed. Defaults to np.array([1.0, 1.0, 1.0]) / np.sqrt(3).
threshold_pointsint64The number of thresholds that we would like to compute. We get thresholds at evenly spaced quantiles on the array of
min_accepted_per_basisint50The minimum number of shots that we require per basis in order to do tomography. This is to prevent very

Returns

(PostselectionCurveData, PostselectionCurveData)PostselectionCurveData: The accepted fractions and point fidelities for the thresholded curve.

source

methodtomography_resultsource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.tomography_result

def tomography_result(accepted_fraction: float) -> TomographyResult

Returns a TomographyResult after decoding and postselection with the option to manually specify the fraction of shots accepted.

The implementation will find the minimum number of shots to accept where the fraction of accepted shots is >= accepted_fraction, sorted by highest to lowest confidence.

Parameters

NameTypeDescription
accepted_fractionfloatThe fraction of shots to accept out of shots that passed postselection. Note that if accepted_fraction == 1.0, this means

Returns

TomographyResultTomographyResult: The resulting shots in each basis based on the accepted_fraction provided.

source

methodanalysis_visualizationsource

bloqade.gemini.decoding.experiments.PostSelectionExperiment.analysis_visualization

Signature
def analysis_visualization(min_accepted_fraction: float = 0.04, title: str | None = None)

Plots the curve of the fidelity vs. accepted fraction, with a cutoff of min_accepted_fraction as well as a supplied title.

Parameters

NameTypeDefaultDescription
min_accepted_fractionfloat0.04
titlestr | NoneNone
source