topqad_sdk.noiseprofiler.libprotocols package
Submodules
topqad_sdk.noiseprofiler.libprotocols.lattice_surgery module
- class topqad_sdk.noiseprofiler.libprotocols.lattice_surgery.LatticeSurgery[source]
Bases:
ProtocolHandler
Lattice surgery is the method by which entangling operations can be performed on surface code qubits. A lattice surgery is equivalent to measuring a joint Pauli operator of two or more qubits. For example, two logical surface code patches could have their $XX$ operator measured. If they are in the $a|++rangle + b|–rangle$ state then the outcome would be $+1$, if they are in $a|+-rangle + b|-+rangle$ state then the outcome would be $-1$, and if they are in any other state, then the outcome would be random.
In this protocol, a lattice surgery is implemented between two surface code patches. Two distinct logical qubits are created in the provided bases. They may be initially stabilized for a few rounds. Then a surface code merge is performed. This takes a logical operator of each of the qubits and joins the two surface code patches along these two operators. This is accomplished with the aid of a bus connecting the two qubit patches. This may entangle the two qubits depending on the bases and operators chosen. The merge code is stabilized for at least $mathcal{O}(d)$ rounds. Finally, the bus region is measured. This is called splitting the code. If done correctly, the stabilizer measurements of the bus yield the value of the joint observable of the merge. The two qubits may be stabilized for an additonal number of rounds before they too are measured.
- add_instance(distance: int, bus_width: int, rounds: tuple[int, int, int], merge_observable: tuple[str, str] = ('X', 'X'), preparation_basis: tuple[str, str] = ('X', 'Z'), measurement_basis: tuple[str, str] = ('Z', 'X'), logical_observable: tuple[str, ...] = ('X1', 'BSX'), *, noise_model_labels: str | list[str] | None = None, decoder='pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
distance (int) – Distance of codes used for the two logical qubits.
bus_width (int) – number of row/column of data qubits added in the routing space.
rounds (tuple[int, int, int]) – number of rounds of the pre-merge, merge, and split phases. merge rounds must be greater than 0. For example, (1, d, 0) is valid.
merge_observable (tuple[str, str], optional) – Joint observable being measured. Only possiblities are (‘X’, ‘X’) and (‘Z’, ‘Z’). Defaults to (‘X’, ‘X’).
preparation_basis (tuple[str, str], optional) – Logical qubits’ initialization basis. Defaults to (‘X’, ‘Z’).
measurement_basis (tuple[str, str], optional) – Logical qubits’ measurement basis. Defaults to (‘Z’, ‘X’).
logical_observable (tuple[str, ...], optional) – The observable used to validate the simulation. It’s a tuple of strings, each of which specifies measurements that must be included in the observable. Possible strings are ‘X0’, ‘X1’, ‘Z0’, ‘Z1’, ‘BSX’, ‘BSZ’, ‘BDX’ and ‘BDZ’. The first four are logical observables of the initial qubits. In the last four ‘B’ stands bus, ‘S’ stands for stabilizer, and ‘D’ stands for data. Defaults to (‘X1’, ‘BSX’).
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
The allowed possibilites of merge_observable, preparation_basis, measurement_basis and logical_observable are stored in the self.valid_observables.
Examples: The default values encode performing and checking teleporting a |+> state from the first to the second qubit, which is initially prepared in |0> using one stabilization round. So
>>> lattice_surgery = libprotocols.LatticeSurgery() >>> lattice_surgery.add_noise_model(libnoise.UniformDepolarizing(p=5e-3)) >>> lattice_surgery.add_instance(distance=3, ... bus_width=3, ... rounds=(1,3,0), ... merge_observable=('X', 'X'), ... preparation_basis=('X', 'Z'), ... measurement_basis=('Z', 'X'), ... logical_observable=('X1', 'BSX') ... )
Here, an XX surgery is performed to move the qubit over. The initial state |+0> after the surgery is either in the |++> or |+-> state. The bus stabilizers should measure +1 or -1 respectively if no errors occur. Hence, to validate this, we compute the product of ‘X1’ and ‘BSX’. It must be +1 if no error occurred.
Another possible lattice surgery is with the combination merge_observable=(‘X’, ‘X’), preparation_basis=(‘X’, ‘X’) and measurement_basis=(‘Z’, ‘X’)). For this key, self.valid_observables stores [‘X1’, ‘BSX’]. This means that logical_observable can be one of (‘X1’,), (‘BSX’, ) or (‘X1’, ‘BSX’).
- fit_data(ind: str, dep: str, noise_model_label: str = 'noise_model', SNR_threshold: float = 5, Abs_threshold: float = inf) tuple[Variable, ...] [source]
Fit data for some combination of variables.
- Parameters:
ind (str) – The independent variable name.
dep (str) – The dependent variable name.
noise_model_label (str) – The noise model for which to fit data. Defaults to “noise_model”.
SNR_threshold (float) – Points with signal-to-noise below this threshold are discarded. Defaults to 5.
Abs_threshold (float) – Points whose value is higher than this absolute threshold are discarded. Defaults to np.inf.
- Raises:
ValueError – If (ind, dep) is not a key in self.fit_options.
- Returns:
The fit parameters as uncertainities Variable types. Use p.nominal_value and p.std_dev to access the stored values.
- Return type:
tuple[Variable, …]
ind=”distance” and dep=”reaction_time” will return the reaction time for a SOTA decoder model.
- fit_options: dict[tuple[str, str], FitSpecification] = {('distance', 'ler'): FitSpecification(fit_ansatz='p_0 * 3 * d**2 * p_1**(-(d+1)/2)', param_bounds=([0, 0], [inf, inf]), y_scale='log', fit_ansatz_latex='{p_0} \\times 3d^2 \\times {p_1}^{{-\\frac{{d+1}}{{2}}}}', ind_math_symbol='d'), ('distance', 'reaction_time'): FitSpecification(fit_ansatz='p_0 * d**p_1', param_bounds=([0, 0], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} d^{p_1}', ind_math_symbol='d'), (('rounds', 1), 'ler'): FitSpecification(fit_ansatz='p_0 * d**2 * p_1**(-(r+1)/2)', param_bounds=([0, 0], [inf, inf]), y_scale='log', fit_ansatz_latex='{p_0} d^2 \\times {p_1}^{{-\\frac{{r+1}}{{2}}}}', ind_math_symbol='r')}
- includes_postselection: bool = False
- protocol_category: str = 'lattice_surgery'
- protocol_name: str = 'lattice_surgery'
- protocol_parameters
alias of
ModelLatticeSurgery
- protocol_subcategory: str = 'emulated'
- valid_observables: dict = {(('X', 'X'), ('X', 'X'), ('X', 'X')): ['X0', 'X1', 'BSX'], (('X', 'X'), ('X', 'X'), ('X', 'Z')): ['X0', 'BSX'], (('X', 'X'), ('X', 'X'), ('Z', 'X')): ['X1', 'BSX'], (('X', 'X'), ('X', 'X'), ('Z', 'Z')): ['BSX'], (('X', 'X'), ('X', 'Z'), ('X', 'X')): ['X0', ('X1', 'BSX')], (('X', 'X'), ('X', 'Z'), ('X', 'Z')): ['X0'], (('X', 'X'), ('X', 'Z'), ('Z', 'X')): [('X1', 'BSX')], (('X', 'X'), ('X', 'Z'), ('Z', 'Z')): [], (('X', 'X'), ('Z', 'X'), ('X', 'X')): ['X1', ('X0', 'BSX')], (('X', 'X'), ('Z', 'X'), ('X', 'Z')): [('X0', 'BSX')], (('X', 'X'), ('Z', 'X'), ('Z', 'X')): ['X1'], (('X', 'X'), ('Z', 'X'), ('Z', 'Z')): [], (('X', 'X'), ('Z', 'Z'), ('X', 'X')): [('X0', 'X1', 'BSX')], (('X', 'X'), ('Z', 'Z'), ('X', 'Z')): [], (('X', 'X'), ('Z', 'Z'), ('Z', 'X')): [], (('X', 'X'), ('Z', 'Z'), ('Z', 'Z')): [('Z0', 'Z1', 'BDZ')], (('Z', 'Z'), ('X', 'X'), ('X', 'X')): [('X0', 'X1', 'BDX')], (('Z', 'Z'), ('X', 'X'), ('X', 'Z')): [], (('Z', 'Z'), ('X', 'X'), ('Z', 'X')): [], (('Z', 'Z'), ('X', 'X'), ('Z', 'Z')): [('Z0', 'Z1', 'BSZ')], (('Z', 'Z'), ('X', 'Z'), ('X', 'X')): [], (('Z', 'Z'), ('X', 'Z'), ('X', 'Z')): ['Z1'], (('Z', 'Z'), ('X', 'Z'), ('Z', 'X')): [('Z0', 'BSZ')], (('Z', 'Z'), ('X', 'Z'), ('Z', 'Z')): ['Z1', ('Z0', 'BSZ')], (('Z', 'Z'), ('Z', 'X'), ('X', 'X')): [], (('Z', 'Z'), ('Z', 'X'), ('X', 'Z')): [('Z1', 'BSZ')], (('Z', 'Z'), ('Z', 'X'), ('Z', 'X')): ['Z0'], (('Z', 'Z'), ('Z', 'X'), ('Z', 'Z')): ['Z0', ('Z1', 'BSZ')], (('Z', 'Z'), ('Z', 'Z'), ('X', 'X')): ['BSZ'], (('Z', 'Z'), ('Z', 'Z'), ('X', 'Z')): ['Z1', 'BSZ'], (('Z', 'Z'), ('Z', 'Z'), ('Z', 'X')): ['Z0', 'BSZ'], (('Z', 'Z'), ('Z', 'Z'), ('Z', 'Z')): ['Z0', 'Z1', 'BSZ']}
- class topqad_sdk.noiseprofiler.libprotocols.lattice_surgery.ModelLatticeSurgery(*, distance: int, bus_width: int, rounds: tuple[int, int, int], merge_observable: tuple[str, str], preparation_basis: tuple[str, str], measurement_basis: tuple[str, str], logical_observable: tuple[str, ...])[source]
Bases:
BaseModel
- bus_width: int
- distance: int
- logical_observable: tuple[str, ...]
- measurement_basis: tuple[str, str]
- merge_observable: tuple[str, str]
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- preparation_basis: tuple[str, str]
- rounds: tuple[int, int, int]
- topqad_sdk.noiseprofiler.libprotocols.lattice_surgery.validate_observable(merge_observable: tuple[str, str], preparation_basis: tuple[str, str], measurement_basis: tuple[str, str], logical_observable: tuple[str, ...]) bool [source]
Validate if requested combination is valid.
- Returns:
True if combination is valid, else False.
- Return type:
bool
topqad_sdk.noiseprofiler.libprotocols.magic_state_preparation_hook_injection module
- class topqad_sdk.noiseprofiler.libprotocols.magic_state_preparation_hook_injection.MagicStatePreparationHookInjection[source]
Bases:
ProtocolHandler
This protocol prepares a logical magic state. It has two stages [1]. In the first stage, two things happen simultaneously. First, a distance 2 surface code patch is created. However, in this process an intentional hook error is introduced that rotates the logical state of the code into the $T$ state. Second, a surface code of distance $d_1$ is created. Consequently, a $T$ logical state is created in a distance $d_1$ surface code. If any detectors trigger in this stage, the protocol is restarted. Otherwise, the second stage proceeds, in which the magic state is grown to a final distance $d_2$.
In this implementation, an analogous protocol is constructed suitable for simulation on a Clifford simulator. Instead of creating a logical $T$ state, a logical $X$ state is created.
### References
[1] C. Gidney, Cleaner Magic States with Hook Injection, arXiv:2302.12292.
- add_instance(d_1: int, d_2: int, r_2: int, inject_state: str = 'X', *, noise_model_labels: str | list[str] | None = None, decoder: str = 'pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
d_1 (int) – The distance of the injection patch created in stage I. Must be odd.
d_2 (int) – The distance of the target patch created during state II. Must be odd and larger than d_1.
r_2 (int) – The number of rounds during stage II.
inject_state (str, optional) – Clifford simulation can be run with either the ‘X’ or ‘Y’ basis states. Defaults to ‘X’. Currently, ‘Y’ is not implemented.
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_options: dict[tuple[str, str], FitSpecification] = {('d_1', 'dr'): FitSpecification(fit_ansatz='p_0 + 0*d_1', param_bounds=([0], [inf]), y_scale='linear', fit_ansatz_latex='{p_0}', ind_math_symbol='d_1'), ('d_2', 'ler'): FitSpecification(fit_ansatz='p_0*d_2 + p_1', param_bounds=([-inf, -inf], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} d_2 + {p_1}', ind_math_symbol='d_2')}
- includes_postselection: bool = True
- protocol_category: str = 'magic_state_preparation_unit'
- protocol_name: str = 'magic_state_preparation_hook_injection'
- protocol_parameters
- protocol_subcategory: str = 'two-stage'
- class topqad_sdk.noiseprofiler.libprotocols.magic_state_preparation_hook_injection.ModelMagicStatePreparationHookInjection(*, d_1: int, d_2: int, r_2: int, inject_state: str)[source]
Bases:
BaseModel
- d_1: int
- d_2: int
- inject_state: str
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- r_2: int
topqad_sdk.noiseprofiler.libprotocols.magic_state_preparation_rep_code module
- class topqad_sdk.noiseprofiler.libprotocols.magic_state_preparation_rep_code.MagicStatePreparationRepCode[source]
Bases:
ProtocolHandler
This protocol prepares a logical magic state. It is inspired by Ref. [1]. Unlike in Ref. [1], this implementation is on the CSS rotated surface code with odd distances. This protocol has two stages. First a two-qubit repetition code is created and its state is rotated with the aid of a two-qubit rotation gate to create a logical magic state. Next, the repetition code is deformed/expanded into a surface code patch. If, during this expansion, any of the detectors trigger, the protocol is restarted. In the second stage, the logical state is grown to some final desired distance.
In this implementation, an analogous protocol is constructed suitable for simulation on a Clifford simulator. Instead of creating a logical $T$ state, a logical $X$ or $Y$ state is created.
### References
[1] Singh et al., High-Fidelity Magic-State Preparation with a Biased-Noise Architecture, Phys. Rev. A 105, 052410 (2022)
- add_instance(distances: list[int | tuple[int, int]], rounds: list[int], inject_state: str = 'X', noise_model_labels: str | list[str] | None = None, decoder='pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
distances (list[int | tuple[int, int]]) – The distances for each of the two stages. Must be odd. If any distance is a tuple, it is treated as (d_x, d_z) for that stage.
rounds (list[int]) – The number of rounds for each of the two stages.
inject_state (str, optional) – Clifford simulation can be run with either the ‘X’ or ‘Y’ basis states. Defaults to ‘X’.
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_options: dict[tuple[str, str], FitSpecification] = {(('distances', 0), 'dr'): FitSpecification(fit_ansatz='p_0 + 0*d_1', param_bounds=([0], [inf]), y_scale='linear', fit_ansatz_latex='{p_0} + {p_1}*d', ind_math_symbol='d_1'), (('distances', 1), 'ler'): FitSpecification(fit_ansatz='p_0 + p_1*d_2', param_bounds=([-inf, -inf], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} + {p_1}*d_2', ind_math_symbol='d_2')}
- includes_postselection: bool = True
- protocol_category: str = 'magic_state_preparation_unit'
- protocol_name: str = 'magic_state_preparation_rep_code'
- protocol_parameters
alias of
ModelMagicStatePreparationRepCode
- protocol_subcategory: str = 'two-stage'
- class topqad_sdk.noiseprofiler.libprotocols.magic_state_preparation_rep_code.ModelMagicStatePreparationRepCode(*, distances: list[int], rounds: list[int], inject_state: str)[source]
Bases:
BaseModel
- distances: list[int]
- inject_state: str
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- rounds: list[int]
topqad_sdk.noiseprofiler.libprotocols.memory module
- class topqad_sdk.noiseprofiler.libprotocols.memory.Memory[source]
Bases:
ProtocolHandler
This protocol is used to protect idle qubits from noise. For simulation, a logical basis state of the rotated surface code of distance $d$ is simultaneously created and stabilized for $r$ rounds. A logical zero state $|0rangle_L$ is created by first indiviually preparing all the physical data qubits in the zero state $|0rangle$ and then the $r$ stabilization rounds are conducted. A plus state $|+rangle_L$ is created similarly, except that the physical data qubits are individually prepared in the plus state $|+rangle$.
To verify that the state was correctly preserved in memory, after r rounds, all data qubits are measured. Then, the value of the logical observable is extracted. For example, to verify that the $|0rangle_L$ was preserved, the logical $Z$ operator is determined by multiplying the value of all data qubits along the top row of the surface code grid. If the value is $+1$, then no logical $X$ error occured to flip the value of the state.
- add_instance(distance: int, rounds: int, basis: str = 'Z', *, noise_model_labels: str | list[str] | None = None, decoder: str = 'pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
distance (int) – Distance of code. Must be odd.
rounds (int) – Number of rounds.
basis (str, optional) – The memory basis. Defaults to ‘Z’.
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_data(ind: str, dep: str, noise_model_label: str = 'noise_model', SNR_threshold: float = 5, Abs_threshold: float = inf) tuple[Variable, ...] [source]
Fit data for some combination of variables.
- Parameters:
ind (str) – The independent variable name.
dep (str) – The dependent variable name.
noise_model_label (str) – The noise model for which to fit data. Defaults to “noise_model”.
SNR_threshold (float) – Points with signal-to-noise below this threshold are discarded. Defaults to 5.
Abs_threshold (float) – Points whose value is higher than this absolute threshold are discarded. Defaults to np.inf.
- Raises:
ValueError – If (ind, dep) is not a key in self.fit_options.
- Returns:
The fit parameters as uncertainities Variable types. Use p.nominal_value and p.std_dev to access the stored values.
- Return type:
tuple[Variable, …]
ind=”distance” and dep=”reaction_time” will return the reaction time for a SOTA decoder model.
- fit_options: dict[tuple[str, str], FitSpecification] = {('distance', 'ler'): FitSpecification(fit_ansatz='p_0 * d**2 * p_1**(-(d+1)/2)', param_bounds=([0, 0], [inf, inf]), y_scale='log', fit_ansatz_latex='{p_0} d^2 \\times {p_1}^{{-\\frac{{d+1}}{{2}}}}', ind_math_symbol='d'), ('distance', 'reaction_time'): FitSpecification(fit_ansatz='p_0 * d**p_1', param_bounds=([0, 0], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} d^{p_1}', ind_math_symbol='d')}
- includes_postselection: bool = False
- protocol_category: str = 'memory'
- protocol_name: str = 'memory'
- protocol_parameters
alias of
ModelMemory
- protocol_subcategory: str = 'emulated'
- class topqad_sdk.noiseprofiler.libprotocols.memory.ModelMemory(*, distance: int, rounds: int, basis: str)[source]
Bases:
BaseModel
- basis: str
- distance: int
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- rounds: int
topqad_sdk.noiseprofiler.libprotocols.models module
- class topqad_sdk.noiseprofiler.libprotocols.models.CodeModel(*, name: CodeName)[source]
Bases:
BaseModel
Code model for noise profiler protocols.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class topqad_sdk.noiseprofiler.libprotocols.models.CodeName(value)[source]
Bases:
str
,Enum
Names of the codes.
- ROTATED_SURFACE_CODE = 'rotated_surface_code'
- class topqad_sdk.noiseprofiler.libprotocols.models.FitDataModel(*, noise_model_label: str, ind: str | tuple[str, int], dep: str, functional_form: str | None = None, ind_math_symbol: str | None = None, fit_bounds: dict[str, list[int | float]] | None = None, fit_parameters: dict[str, FitParametersModel] | None = None)[source]
Bases:
BaseModel
Data for fitting in noise profiler protocols.
- dep: str
- fit_bounds: dict[str, list[int | float]] | None
- fit_parameters: dict[str, FitParametersModel] | None
- functional_form: str | None
- ind: str | tuple[str, int]
- ind_math_symbol: str | None
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- noise_model_label: str
- class topqad_sdk.noiseprofiler.libprotocols.models.FitParametersModel(*, value: float, error: float)[source]
Bases:
BaseModel
Parameters for fitting data in noise profiler protocols.
- error: float
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- value: float
- class topqad_sdk.noiseprofiler.libprotocols.models.PlotParametersModel(*, ind: str, dep: str, fit: bool, extrapolate: bool, extrapolate_to_dep: float, save_fig: bool | None = None, save_fig_dir: str | None = None, save_fig_filename: str | None = None)[source]
Bases:
BaseModel
Parameters for plotting in noise profiler protocols.
- dep: str
- extrapolate: bool
- extrapolate_to_dep: float
- fit: bool
- ind: str
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- save_fig: bool | None
- save_fig_dir: str | None
- save_fig_filename: str | None
- class topqad_sdk.noiseprofiler.libprotocols.models.ProtocolName(value)[source]
Bases:
str
,Enum
Names of the protocols.
- LATTICE_SURGERY = 'lattice_surgery'
- MAGIC_STATE_PREPARATION_CULTIVATION = 'magic_state_preparation_cultivation'
- MAGIC_STATE_PREPARATION_HOOK_INJECTION = 'magic_state_preparation_hook_injection'
- MAGIC_STATE_PREPARATION_REP_CODE = 'magic_state_preparation_rep_code'
- MEMORY = 'memory'
- STABILITY = 'stability'
- class topqad_sdk.noiseprofiler.libprotocols.models.ProtocolSpecificationModel(*, protocol_category: str | None = None, protocol_subcategory: str | None = None, protocol_name: ProtocolName, code: CodeModel, simulation_table: SimTableModel, noise_models: list[NoiseModelSpecificationModel], simulation_parameters: SimulationParametersModel | None = None, fits: list[FitDataModel] | None = None, plots: list[PlotParametersModel] | None = None, stabilization_times: list[StabilizationTime] | None = None)[source]
Bases:
BaseModel
Specification model for noise profiler protocols.
- fits: list[FitDataModel] | None
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- noise_models: list[NoiseModelSpecificationModel]
- plots: list[PlotParametersModel] | None
- protocol_category: str | None
- protocol_name: ProtocolName
- protocol_subcategory: str | None
- simulation_parameters: SimulationParametersModel | None
- simulation_table: SimTableModel
- stabilization_times: list[StabilizationTime] | None
- class topqad_sdk.noiseprofiler.libprotocols.models.SimulationParametersModel(*, max_n_samples: int, signal_to_noise: int)[source]
Bases:
BaseModel
Simulation parameters for noise profiler protocols.
- max_n_samples: int
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- signal_to_noise: int
- class topqad_sdk.noiseprofiler.libprotocols.models.StabilizationTime(*, noise_model_label: str, stabilization_time: Quantity)[source]
Bases:
BaseModel
Stabilization time for noise profiler protocols.
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- noise_model_label: str
topqad_sdk.noiseprofiler.libprotocols.protocol_handler module
- class topqad_sdk.noiseprofiler.libprotocols.protocol_handler.FitSpecification(fit_ansatz: str, param_bounds: tuple[list, list], y_scale: str, fit_ansatz_latex: str, ind_math_symbol: str)[source]
Bases:
object
Contains all information to specify a fit for a given class of curves.
- Parameters:
fit_ansatz (Callable) – The fit function.
param_bounds (tuple[list, list]) – The parameter bounds.
y_scale (str) – Either ‘linear’ or ‘log’.
fit_ansatz_latex (str) – The latex description of the fit function. Use raw strings.
Examples
- def fit_ansatz_memory_d_ler(distance, p_1, p_2):
return -(distance+1)/2 * np.log(p_2) + 2*np.log(distance) + np.log(p_1)
- FitSpecification(fit_ansatz=fit_ansatz_memory_d_ler,
param_bounds=([0, 0], [np.inf, np.inf]), y_scale=’log’, fit_ansatz_latex=r”{p_1} d^2 times {p_2}^{{-frac{{d+1}}{{2}}}}”, )
- fit_ansatz: str
- fit_ansatz_latex: str
- ind_math_symbol: str
- param_bounds: tuple[list, list]
- y_scale: str
- class topqad_sdk.noiseprofiler.libprotocols.protocol_handler.ProtocolHandler[source]
Bases:
object
Handler class for working with FTQC protocols.
- To work with a protocol, one needs to be able to
generate instances of the protocol,
simulate the protocol instances and collect data
fit the data
plot the data
This class contains functionality to do all of this.
- Parameters:
protocol_category (str) – The main protocol category, such as “memory” or “magic_state_preparation_unit”.
protocol_subcategory (str) – The subcategory if there are various kinds of say “memory” protocols.
protocol_name (str) – The unique name of the protocol such as “magic_state_preparation_rep_code”.
protocol_parameters (BaseModel) – A pydantic model that specifies all the protocol parameters.
fit_options (dict[tuple[str, str], FitSpecification]) – A dictionary mapping (ind, dep) parameters to a fit specification. These fit options will then be used by the fitting and plotting routines.
includes_postselection (bool) – Whether the protocol has post-selection in it.
simulation_table (SimTable) – Contains all data related to the simulation statistics.
noise_models (dict[str | float | tuple[str, float], NoiseModel]) – dictionary of noise models with their labels as keys.
simulation_parameters (dict[str, Any]) – simulation parameters. Use set_simulation_parameters method to change these.
- add_instance(*, noise_model_labels: str | float | tuple[str, float] | list[str | float | tuple[str, float]] | None = None, decoder='pymatching', **kwargs)[source]
Add instance of protocol parameters to be simulated.
This method should be overridden to explicitly specify the protocol parameters with types.
- add_noise_model(noise_model: NoiseModel, *, label: str | float | tuple[str, float] = 'noise_model') None [source]
Add a noise model that will be used in simulations.
Multiple noise models can be added. Each one should have a unique label (label_str, label_numeric).
- Parameters:
noise_model (NoiseModel) – The noise model to add.
label (str | float | tuple[str, float], optional) – The label for the parameters. Defaults to ‘noise_model’.
- Raises:
ValueError – If noise_model is not a noise model.
Exception – If label is already used for an existing noise model.
- execute_simulation() None [source]
Execute the simulation for the protocol instances specified in the simulation table.
The Noise Profiler simulator uses a heuristic to avoid simulations that are unlikely to yield good statistics. It first collects $10%$ of the samples. If no errors are observed, then the remaining samples are not collected. In this case, the output statistical parameters will have the value “F” (indicating failure).
- fit_data(ind: str, dep: str, noise_model_label: str = 'noise_model', SNR_threshold: float = 5, Abs_threshold: float = inf) tuple[Variable, ...] [source]
Fit data for some combination of variables.
The fit function used must be present in self.fit_options[ind, dep].
- Parameters:
ind (str) – The independent variable name.
dep (str) – The dependent variable name.
noise_model_label (str) – The noise model for which to fit data. Defaults to “noise_model”.
SNR_threshold (float) – Points with signal-to-noise below this threshold are discarded. Defaults to 5.
Abs_threshold (float) – Points whose value is higher than this absolute threshold are discarded. Defaults to np.inf.
- Raises:
ValueError – If (ind, dep) is not a key in self.fit_options.
- Returns:
The fit parameters as uncertainities Variable types. Use p.nominal_value and p.std_dev to access the stored values.
- Return type:
tuple[Variable, …]
- fit_options: dict[tuple[str, str], FitSpecification]
- includes_postselection: bool
- plot(ind: str, dep: str, fit: bool = False, SNR_threshold: float = 5, Abs_threshold: float = inf, extrapolate: bool = False, extrapolate_to_dep: float = 1e-08, save_fig: bool = False, save_fig_dir: str = 'data/output', save_fig_filename: str | None = None, ax: Axes | None = None)[source]
Plot the collected simulation data.
Each noise model data is plotted as a separate line on the plot.
- Parameters:
ind (str) – The independent variable to use on the horizontal axis.
dep (str) – The dependent variable to use on the vertical axis. Can only be “ler” or “dr”.
fit (bool, optional) – Whether to fit the data. Defaults to False.
SNR_threshold (float) – Points with signal-to-noise below this threshold are discarded for fits. Defaults to 5.
Abs_threshold (float) – Points whose value is higher than this absolute threshold are discarded for fits. Defaults to np.inf.
extrapolate (bool, optional) – Whether to extrapolate the dep var to. Defaults to False.
extrapolate_to_dep (float, optional) – The value to extrapolate the dep var to. Defaults to 1e-8.
save_fig (bool, optional) – Whether to safe the figure. Defaults to False.
save_fig_dir (str, optional) – Directory in which figure is saved. Directory is created if needed. Defaults to ‘data/output’.
save_fig_filename (str, optional) – Filename of saved figure. Defaults to f’plot_{self.protocol_name}_{ind}_{dep}.png’.
ax (Axes, optional) – A matplotlib Axes. If passed, then the plot is added to this axis. Defaults to None.
- Raises:
ValueError – If (ind, dep) is not a key in self.fit_options.
ValueError – If ax is not None or does not have type Axes.
ValueError – If extrapolation fails.
Exception – Fitting failed to yield reasonable values.
- protocol_category: str
- protocol_name: str
- protocol_parameters: BaseModel
- protocol_subcategory: str
- set_simulation_parameters(max_n_samples: int = 100000000, signal_to_noise: float = 10, num_workers: int = 8, save_data: bool = False, save_data_dir: str = 'data/output', save_data_filename: str | None = None)[source]
Set simulation parameters
- Parameters:
max_n_samples (int, optional) – The maximum samples that will be collected. Defaults to 10**8.
signal_to_noise (float, optional) – Signal to noise ratio used to determine how many samples will be collected. Defaults to 10.
num_workers (int, optional) – The number of worker processes that sinter should use. Defaults to 8.
save_data (bool, optional) – Whether to save simulation data to file.
save_data_dir (str, optional) – Directory where data file is saved, which is created if needed. Defaults to ‘data/output’.
save_data_filename (str, optional) – The name of the pickle file containing list[stim.TaskStats]. Defaults to f”simulation_table_{self.protocol_name}.pkl”.
- topqad_sdk.noiseprofiler.libprotocols.protocol_handler.u_format(x: Variable, separate: bool = False) str [source]
Format a variable with uncertainity Y as a string in form X.XX(Y).
- Parameters:
x (Variable) – The number to format.
separate (bool, optional) – Controls if the nominal and std dev values are separated. If True output is a tuple of form (X.XX, 0.0Y). Defaults to False.
- Returns:
The formatted number.
- Return type:
str | tuple
Examples
2.34 ± 0.013 -> 2.34(1) 8.12 ± 0.3 -> 8.1(3) 18.15 ± 1.1 -> 18(1)
topqad_sdk.noiseprofiler.libprotocols.stability module
- class topqad_sdk.noiseprofiler.libprotocols.stability.ModelStability(*, rounds: int, diameter: int | tuple[int, int])[source]
Bases:
BaseModel
- diameter: int | tuple[int, int]
- model_config: ClassVar[ConfigDict] = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- rounds: int
- class topqad_sdk.noiseprofiler.libprotocols.stability.Stability[source]
Bases:
ProtocolHandler
The stability protocol [1] is used to estimate how well a fault-tolerant system can move logical observables through space or, equivalently, determine the product of a large region of stabilizers. Logical observables are, for example, moved through space in lattice surgery operations.
### References
[1] Gidney et al, Stability Experiments: The Overlooked Dual of Memory Experiments, Quantum 6, 786 (2022)
- add_instance(rounds: int, diameter: int | tuple[int, int], *, noise_model_labels: str | list[str] | None = None, decoder='pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
rounds (int) – Number of rounds (temporal distance).
diameter (int | tuple[int, int]) – Spatial distance of code. Must be even. Can separately specify (d_x, d_z).
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_options: dict[tuple[str, str], FitSpecification] = {}
- includes_postselection: bool = False
- protocol_category: str = 'stability'
- protocol_name: str = 'stability'
- protocol_parameters
alias of
ModelStability
- protocol_subcategory: str = 'emulated'
Module contents
The available protocols are:
LatticeSurgery
MagicStatePreparationHookInjection
MagicStatePreparationRepCode
Memory
Stability
- class topqad_sdk.noiseprofiler.libprotocols.LatticeSurgery[source]
Bases:
ProtocolHandler
Lattice surgery is the method by which entangling operations can be performed on surface code qubits. A lattice surgery is equivalent to measuring a joint Pauli operator of two or more qubits. For example, two logical surface code patches could have their $XX$ operator measured. If they are in the $a|++rangle + b|–rangle$ state then the outcome would be $+1$, if they are in $a|+-rangle + b|-+rangle$ state then the outcome would be $-1$, and if they are in any other state, then the outcome would be random.
In this protocol, a lattice surgery is implemented between two surface code patches. Two distinct logical qubits are created in the provided bases. They may be initially stabilized for a few rounds. Then a surface code merge is performed. This takes a logical operator of each of the qubits and joins the two surface code patches along these two operators. This is accomplished with the aid of a bus connecting the two qubit patches. This may entangle the two qubits depending on the bases and operators chosen. The merge code is stabilized for at least $mathcal{O}(d)$ rounds. Finally, the bus region is measured. This is called splitting the code. If done correctly, the stabilizer measurements of the bus yield the value of the joint observable of the merge. The two qubits may be stabilized for an additonal number of rounds before they too are measured.
- add_instance(distance: int, bus_width: int, rounds: tuple[int, int, int], merge_observable: tuple[str, str] = ('X', 'X'), preparation_basis: tuple[str, str] = ('X', 'Z'), measurement_basis: tuple[str, str] = ('Z', 'X'), logical_observable: tuple[str, ...] = ('X1', 'BSX'), *, noise_model_labels: str | list[str] | None = None, decoder='pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
distance (int) – Distance of codes used for the two logical qubits.
bus_width (int) – number of row/column of data qubits added in the routing space.
rounds (tuple[int, int, int]) – number of rounds of the pre-merge, merge, and split phases. merge rounds must be greater than 0. For example, (1, d, 0) is valid.
merge_observable (tuple[str, str], optional) – Joint observable being measured. Only possiblities are (‘X’, ‘X’) and (‘Z’, ‘Z’). Defaults to (‘X’, ‘X’).
preparation_basis (tuple[str, str], optional) – Logical qubits’ initialization basis. Defaults to (‘X’, ‘Z’).
measurement_basis (tuple[str, str], optional) – Logical qubits’ measurement basis. Defaults to (‘Z’, ‘X’).
logical_observable (tuple[str, ...], optional) – The observable used to validate the simulation. It’s a tuple of strings, each of which specifies measurements that must be included in the observable. Possible strings are ‘X0’, ‘X1’, ‘Z0’, ‘Z1’, ‘BSX’, ‘BSZ’, ‘BDX’ and ‘BDZ’. The first four are logical observables of the initial qubits. In the last four ‘B’ stands bus, ‘S’ stands for stabilizer, and ‘D’ stands for data. Defaults to (‘X1’, ‘BSX’).
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
The allowed possibilites of merge_observable, preparation_basis, measurement_basis and logical_observable are stored in the self.valid_observables.
Examples: The default values encode performing and checking teleporting a |+> state from the first to the second qubit, which is initially prepared in |0> using one stabilization round. So
>>> lattice_surgery = libprotocols.LatticeSurgery() >>> lattice_surgery.add_noise_model(libnoise.UniformDepolarizing(p=5e-3)) >>> lattice_surgery.add_instance(distance=3, ... bus_width=3, ... rounds=(1,3,0), ... merge_observable=('X', 'X'), ... preparation_basis=('X', 'Z'), ... measurement_basis=('Z', 'X'), ... logical_observable=('X1', 'BSX') ... )
Here, an XX surgery is performed to move the qubit over. The initial state |+0> after the surgery is either in the |++> or |+-> state. The bus stabilizers should measure +1 or -1 respectively if no errors occur. Hence, to validate this, we compute the product of ‘X1’ and ‘BSX’. It must be +1 if no error occurred.
Another possible lattice surgery is with the combination merge_observable=(‘X’, ‘X’), preparation_basis=(‘X’, ‘X’) and measurement_basis=(‘Z’, ‘X’)). For this key, self.valid_observables stores [‘X1’, ‘BSX’]. This means that logical_observable can be one of (‘X1’,), (‘BSX’, ) or (‘X1’, ‘BSX’).
- fit_data(ind: str, dep: str, noise_model_label: str = 'noise_model', SNR_threshold: float = 5, Abs_threshold: float = inf) tuple[Variable, ...] [source]
Fit data for some combination of variables.
- Parameters:
ind (str) – The independent variable name.
dep (str) – The dependent variable name.
noise_model_label (str) – The noise model for which to fit data. Defaults to “noise_model”.
SNR_threshold (float) – Points with signal-to-noise below this threshold are discarded. Defaults to 5.
Abs_threshold (float) – Points whose value is higher than this absolute threshold are discarded. Defaults to np.inf.
- Raises:
ValueError – If (ind, dep) is not a key in self.fit_options.
- Returns:
The fit parameters as uncertainities Variable types. Use p.nominal_value and p.std_dev to access the stored values.
- Return type:
tuple[Variable, …]
ind=”distance” and dep=”reaction_time” will return the reaction time for a SOTA decoder model.
- fit_options: dict[tuple[str, str], FitSpecification] = {('distance', 'ler'): FitSpecification(fit_ansatz='p_0 * 3 * d**2 * p_1**(-(d+1)/2)', param_bounds=([0, 0], [inf, inf]), y_scale='log', fit_ansatz_latex='{p_0} \\times 3d^2 \\times {p_1}^{{-\\frac{{d+1}}{{2}}}}', ind_math_symbol='d'), ('distance', 'reaction_time'): FitSpecification(fit_ansatz='p_0 * d**p_1', param_bounds=([0, 0], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} d^{p_1}', ind_math_symbol='d'), (('rounds', 1), 'ler'): FitSpecification(fit_ansatz='p_0 * d**2 * p_1**(-(r+1)/2)', param_bounds=([0, 0], [inf, inf]), y_scale='log', fit_ansatz_latex='{p_0} d^2 \\times {p_1}^{{-\\frac{{r+1}}{{2}}}}', ind_math_symbol='r')}
- includes_postselection: bool = False
- noise_models: dict[str | float | tuple[str, float], NoiseModel]
- protocol_category: str = 'lattice_surgery'
- protocol_name: str = 'lattice_surgery'
- protocol_parameters
alias of
ModelLatticeSurgery
- protocol_subcategory: str = 'emulated'
- valid_observables: dict = {(('X', 'X'), ('X', 'X'), ('X', 'X')): ['X0', 'X1', 'BSX'], (('X', 'X'), ('X', 'X'), ('X', 'Z')): ['X0', 'BSX'], (('X', 'X'), ('X', 'X'), ('Z', 'X')): ['X1', 'BSX'], (('X', 'X'), ('X', 'X'), ('Z', 'Z')): ['BSX'], (('X', 'X'), ('X', 'Z'), ('X', 'X')): ['X0', ('X1', 'BSX')], (('X', 'X'), ('X', 'Z'), ('X', 'Z')): ['X0'], (('X', 'X'), ('X', 'Z'), ('Z', 'X')): [('X1', 'BSX')], (('X', 'X'), ('X', 'Z'), ('Z', 'Z')): [], (('X', 'X'), ('Z', 'X'), ('X', 'X')): ['X1', ('X0', 'BSX')], (('X', 'X'), ('Z', 'X'), ('X', 'Z')): [('X0', 'BSX')], (('X', 'X'), ('Z', 'X'), ('Z', 'X')): ['X1'], (('X', 'X'), ('Z', 'X'), ('Z', 'Z')): [], (('X', 'X'), ('Z', 'Z'), ('X', 'X')): [('X0', 'X1', 'BSX')], (('X', 'X'), ('Z', 'Z'), ('X', 'Z')): [], (('X', 'X'), ('Z', 'Z'), ('Z', 'X')): [], (('X', 'X'), ('Z', 'Z'), ('Z', 'Z')): [('Z0', 'Z1', 'BDZ')], (('Z', 'Z'), ('X', 'X'), ('X', 'X')): [('X0', 'X1', 'BDX')], (('Z', 'Z'), ('X', 'X'), ('X', 'Z')): [], (('Z', 'Z'), ('X', 'X'), ('Z', 'X')): [], (('Z', 'Z'), ('X', 'X'), ('Z', 'Z')): [('Z0', 'Z1', 'BSZ')], (('Z', 'Z'), ('X', 'Z'), ('X', 'X')): [], (('Z', 'Z'), ('X', 'Z'), ('X', 'Z')): ['Z1'], (('Z', 'Z'), ('X', 'Z'), ('Z', 'X')): [('Z0', 'BSZ')], (('Z', 'Z'), ('X', 'Z'), ('Z', 'Z')): ['Z1', ('Z0', 'BSZ')], (('Z', 'Z'), ('Z', 'X'), ('X', 'X')): [], (('Z', 'Z'), ('Z', 'X'), ('X', 'Z')): [('Z1', 'BSZ')], (('Z', 'Z'), ('Z', 'X'), ('Z', 'X')): ['Z0'], (('Z', 'Z'), ('Z', 'X'), ('Z', 'Z')): ['Z0', ('Z1', 'BSZ')], (('Z', 'Z'), ('Z', 'Z'), ('X', 'X')): ['BSZ'], (('Z', 'Z'), ('Z', 'Z'), ('X', 'Z')): ['Z1', 'BSZ'], (('Z', 'Z'), ('Z', 'Z'), ('Z', 'X')): ['Z0', 'BSZ'], (('Z', 'Z'), ('Z', 'Z'), ('Z', 'Z')): ['Z0', 'Z1', 'BSZ']}
- class topqad_sdk.noiseprofiler.libprotocols.MagicStatePreparationHookInjection[source]
Bases:
ProtocolHandler
This protocol prepares a logical magic state. It has two stages [1]. In the first stage, two things happen simultaneously. First, a distance 2 surface code patch is created. However, in this process an intentional hook error is introduced that rotates the logical state of the code into the $T$ state. Second, a surface code of distance $d_1$ is created. Consequently, a $T$ logical state is created in a distance $d_1$ surface code. If any detectors trigger in this stage, the protocol is restarted. Otherwise, the second stage proceeds, in which the magic state is grown to a final distance $d_2$.
In this implementation, an analogous protocol is constructed suitable for simulation on a Clifford simulator. Instead of creating a logical $T$ state, a logical $X$ state is created.
### References
[1] C. Gidney, Cleaner Magic States with Hook Injection, arXiv:2302.12292.
- add_instance(d_1: int, d_2: int, r_2: int, inject_state: str = 'X', *, noise_model_labels: str | list[str] | None = None, decoder: str = 'pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
d_1 (int) – The distance of the injection patch created in stage I. Must be odd.
d_2 (int) – The distance of the target patch created during state II. Must be odd and larger than d_1.
r_2 (int) – The number of rounds during stage II.
inject_state (str, optional) – Clifford simulation can be run with either the ‘X’ or ‘Y’ basis states. Defaults to ‘X’. Currently, ‘Y’ is not implemented.
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_options: dict[tuple[str, str], FitSpecification] = {('d_1', 'dr'): FitSpecification(fit_ansatz='p_0 + 0*d_1', param_bounds=([0], [inf]), y_scale='linear', fit_ansatz_latex='{p_0}', ind_math_symbol='d_1'), ('d_2', 'ler'): FitSpecification(fit_ansatz='p_0*d_2 + p_1', param_bounds=([-inf, -inf], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} d_2 + {p_1}', ind_math_symbol='d_2')}
- includes_postselection: bool = True
- noise_models: dict[str | float | tuple[str, float], NoiseModel]
- protocol_category: str = 'magic_state_preparation_unit'
- protocol_name: str = 'magic_state_preparation_hook_injection'
- protocol_parameters
- protocol_subcategory: str = 'two-stage'
- class topqad_sdk.noiseprofiler.libprotocols.MagicStatePreparationRepCode[source]
Bases:
ProtocolHandler
This protocol prepares a logical magic state. It is inspired by Ref. [1]. Unlike in Ref. [1], this implementation is on the CSS rotated surface code with odd distances. This protocol has two stages. First a two-qubit repetition code is created and its state is rotated with the aid of a two-qubit rotation gate to create a logical magic state. Next, the repetition code is deformed/expanded into a surface code patch. If, during this expansion, any of the detectors trigger, the protocol is restarted. In the second stage, the logical state is grown to some final desired distance.
In this implementation, an analogous protocol is constructed suitable for simulation on a Clifford simulator. Instead of creating a logical $T$ state, a logical $X$ or $Y$ state is created.
### References
[1] Singh et al., High-Fidelity Magic-State Preparation with a Biased-Noise Architecture, Phys. Rev. A 105, 052410 (2022)
- add_instance(distances: list[int | tuple[int, int]], rounds: list[int], inject_state: str = 'X', noise_model_labels: str | list[str] | None = None, decoder='pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
distances (list[int | tuple[int, int]]) – The distances for each of the two stages. Must be odd. If any distance is a tuple, it is treated as (d_x, d_z) for that stage.
rounds (list[int]) – The number of rounds for each of the two stages.
inject_state (str, optional) – Clifford simulation can be run with either the ‘X’ or ‘Y’ basis states. Defaults to ‘X’.
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_options: dict[tuple[str, str], FitSpecification] = {(('distances', 0), 'dr'): FitSpecification(fit_ansatz='p_0 + 0*d_1', param_bounds=([0], [inf]), y_scale='linear', fit_ansatz_latex='{p_0} + {p_1}*d', ind_math_symbol='d_1'), (('distances', 1), 'ler'): FitSpecification(fit_ansatz='p_0 + p_1*d_2', param_bounds=([-inf, -inf], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} + {p_1}*d_2', ind_math_symbol='d_2')}
- includes_postselection: bool = True
- noise_models: dict[str | float | tuple[str, float], NoiseModel]
- protocol_category: str = 'magic_state_preparation_unit'
- protocol_name: str = 'magic_state_preparation_rep_code'
- protocol_parameters
alias of
ModelMagicStatePreparationRepCode
- protocol_subcategory: str = 'two-stage'
- class topqad_sdk.noiseprofiler.libprotocols.Memory[source]
Bases:
ProtocolHandler
This protocol is used to protect idle qubits from noise. For simulation, a logical basis state of the rotated surface code of distance $d$ is simultaneously created and stabilized for $r$ rounds. A logical zero state $|0rangle_L$ is created by first indiviually preparing all the physical data qubits in the zero state $|0rangle$ and then the $r$ stabilization rounds are conducted. A plus state $|+rangle_L$ is created similarly, except that the physical data qubits are individually prepared in the plus state $|+rangle$.
To verify that the state was correctly preserved in memory, after r rounds, all data qubits are measured. Then, the value of the logical observable is extracted. For example, to verify that the $|0rangle_L$ was preserved, the logical $Z$ operator is determined by multiplying the value of all data qubits along the top row of the surface code grid. If the value is $+1$, then no logical $X$ error occured to flip the value of the state.
- add_instance(distance: int, rounds: int, basis: str = 'Z', *, noise_model_labels: str | list[str] | None = None, decoder: str = 'pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
distance (int) – Distance of code. Must be odd.
rounds (int) – Number of rounds.
basis (str, optional) – The memory basis. Defaults to ‘Z’.
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_data(ind: str, dep: str, noise_model_label: str = 'noise_model', SNR_threshold: float = 5, Abs_threshold: float = inf) tuple[Variable, ...] [source]
Fit data for some combination of variables.
- Parameters:
ind (str) – The independent variable name.
dep (str) – The dependent variable name.
noise_model_label (str) – The noise model for which to fit data. Defaults to “noise_model”.
SNR_threshold (float) – Points with signal-to-noise below this threshold are discarded. Defaults to 5.
Abs_threshold (float) – Points whose value is higher than this absolute threshold are discarded. Defaults to np.inf.
- Raises:
ValueError – If (ind, dep) is not a key in self.fit_options.
- Returns:
The fit parameters as uncertainities Variable types. Use p.nominal_value and p.std_dev to access the stored values.
- Return type:
tuple[Variable, …]
ind=”distance” and dep=”reaction_time” will return the reaction time for a SOTA decoder model.
- fit_options: dict[tuple[str, str], FitSpecification] = {('distance', 'ler'): FitSpecification(fit_ansatz='p_0 * d**2 * p_1**(-(d+1)/2)', param_bounds=([0, 0], [inf, inf]), y_scale='log', fit_ansatz_latex='{p_0} d^2 \\times {p_1}^{{-\\frac{{d+1}}{{2}}}}', ind_math_symbol='d'), ('distance', 'reaction_time'): FitSpecification(fit_ansatz='p_0 * d**p_1', param_bounds=([0, 0], [inf, inf]), y_scale='linear', fit_ansatz_latex='{p_0} d^{p_1}', ind_math_symbol='d')}
- includes_postselection: bool = False
- noise_models: dict[str | float | tuple[str, float], NoiseModel]
- protocol_category: str = 'memory'
- protocol_name: str = 'memory'
- protocol_parameters
alias of
ModelMemory
- protocol_subcategory: str = 'emulated'
- class topqad_sdk.noiseprofiler.libprotocols.Stability[source]
Bases:
ProtocolHandler
The stability protocol [1] is used to estimate how well a fault-tolerant system can move logical observables through space or, equivalently, determine the product of a large region of stabilizers. Logical observables are, for example, moved through space in lattice surgery operations.
### References
[1] Gidney et al, Stability Experiments: The Overlooked Dual of Memory Experiments, Quantum 6, 786 (2022)
- add_instance(rounds: int, diameter: int | tuple[int, int], *, noise_model_labels: str | list[str] | None = None, decoder='pymatching')[source]
Add instance of protocol parameters to be simulated.
- Parameters:
rounds (int) – Number of rounds (temporal distance).
diameter (int | tuple[int, int]) – Spatial distance of code. Must be even. Can separately specify (d_x, d_z).
noise_model_label (str | list[str] | None, optional) – The noise model label(s) for this instance. If None, then all added noise models are used. Default is None.
decoder (str, optional) – The decoder to use. “pymatching” is the only option.
- fit_options: dict[tuple[str, str], FitSpecification] = {}
- includes_postselection: bool = False
- noise_models: dict[str | float | tuple[str, float], NoiseModel]
- protocol_category: str = 'stability'
- protocol_name: str = 'stability'
- protocol_parameters
alias of
ModelStability
- protocol_subcategory: str = 'emulated'