bloqade.gemini.decoding.experiments.PostSelectionExperiment
classPostSelectionExperiment¶source
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
| Name | Type | Default | Description |
|---|---|---|---|
nonclifford_prefix | ir.Method[..., None] | required | |
clifford_circuit | ir.Method[..., None] | required | |
tomography_circuits | Mapping[str, ir.Method[..., None]] | required | |
decoder | type[ConfidenceDecoder] | required | |
decoder_init_args | Mapping[str, object] | None | None |
Attributes
| Name | Type | Description |
|---|---|---|
nonclifford_prefix | ir.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_circuit | ir.Method[..., None] | A SQuIN kernel consisting of a Clifford circuit applied to the logical qubits (after logical encoding). |
tomography_circuits | ir.Method[..., None] | A mapping of basis strings to SQuIN kernels consisting of a clifford circuit applied to your logical qubits. |
These | kernels 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. |
decoder | type[ConfidenceDecoder] | A type of ConfidenceDecoder used to initialize decoders. |
decoder_init_args | Mapping[str, object] | None | Optional arguments that can be passed in to initialize the decoder. Defaults to None. |
methodkernels¶source
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
| Name | Type | Default | Description |
|---|---|---|---|
num_logical_qubits | int | 5 | An 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.
methoddem_circuits¶source
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.
methoddems¶source
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.
methodinitialize_decoders¶source
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.
methodmake_tasks¶source
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
| Name | Type | Description |
|---|---|---|
device | GeminiLogicalSimulator |
Returns
dict[str, GeminiLogicalSimulatorTask[_LogicalTomographyReturn]]
methodget_samples¶source
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
| Name | Type | Description |
|---|---|---|
num_shots | int |
Returns
dict[str, _BasisDataset]
methoddecode_and_postselect¶source
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:
- Decoding and correction on the ancilla qubits
- Filtering shots whose corrected ancilla observable is a valid pattern in postselection_condition
- Out of these filtered shots, decode and correct the output qubit
- Returns the corrected observables as well as the confidence score associated with each observable.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
postselection_condition | np.ndarray | required | A 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_label | str | bool | False | If 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.
methodanalysis_f_vs_fraction¶source
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) -> PostselectionCurveDataAnalyzes 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
| Name | Type | Default | Description |
|---|---|---|---|
target_bloch | np.ndarray | _DEFAULT_TARGET_BLOCH | The bloch vector to which fidelity is computed. Defaults to np.array([1.0, 1.0, 1.0]) / np.sqrt(3). |
threshold_points | int | 64 | The number of thresholds that we would like to compute. We get thresholds at evenly spaced quantiles on the array of |
min_accepted_per_basis | int | 50 | The 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.
methodtomography_result¶source
bloqade.gemini.decoding.experiments.PostSelectionExperiment.tomography_result
def tomography_result(accepted_fraction: float) -> TomographyResultReturns 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
| Name | Type | Description |
|---|---|---|
accepted_fraction | float | The 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.
methodanalysis_visualization¶source
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
| Name | Type | Default | Description |
|---|---|---|---|
min_accepted_fraction | float | 0.04 | |
title | str | None | None |