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
enforce_maximum_values()[source]
classmethod is_bus_width(value: int)[source]
classmethod is_distance(value: int)[source]
classmethod is_logical_observable(value: tuple[str, ...])[source]
classmethod is_measurement_basis(value: tuple[str, str])[source]
classmethod is_merge_observable(value: str)[source]
classmethod is_preparation_basis(value: tuple[str, str])[source]
classmethod is_rounds(value: tuple[int, int, int])[source]
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]
valid_combination()[source]
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

alias of ModelMagicStatePreparationHookInjection

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

check_distances()[source]
d_1: int
d_2: int
enforce_maximum_values()[source]
inject_state: str
classmethod is_distance(d_i: int)[source]
classmethod is_inject_state(value: str)[source]
classmethod is_round(r_2: int)[source]
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]
enforce_maximum_values()[source]
inject_state: str
classmethod is_distances(distances: list[int])[source]
classmethod is_inject_state(inject_state: str)[source]
classmethod is_rounds(rounds: list[int])[source]
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
enforce_maximum_values()[source]
classmethod is_basis(basis: str)[source]
classmethod is_distance(value: int)[source]
classmethod is_round(value: int)[source]
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].

name: CodeName
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.

code: CodeModel
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.

enforce_maximum_values()[source]
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
stabilization_time: Quantity

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]
enforce_maximum_values()[source]
classmethod is_diameter(value: int | tuple[int, int])[source]
classmethod is_round(value: int)[source]
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:

  1. LatticeSurgery

  2. MagicStatePreparationHookInjection

  3. MagicStatePreparationRepCode

  4. Memory

  5. 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'
simulation_table: SimTable
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

alias of ModelMagicStatePreparationHookInjection

protocol_subcategory: str = 'two-stage'
simulation_table: SimTable
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'
simulation_table: SimTable
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'
simulation_table: SimTable
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'
simulation_table: SimTable