# Error Generators¶

Error models are represented by classes called “error generators” that are in the `error_gens`

namespace. They are called upon by `circuit_runners`

to apply noise to ideal quantum circuits.

In this section I will discuss `GatewiseGen`

and `DepolarGen`

classes. Both represent `stochastic error models`

. That is, error models that apply gates as noise according to classical probability distributions.

## GatewiseGen¶

The `GatewiseGen`

class allow one to define custom stochastic error-models where for each ideal gate-type the errors applied to the ideal gate and the classical probability distribution for applying errors can be specified. Since many examples of using the class are given, I have moved the discussion of the `GatewiseGen`

class to Gate-wise Error Models.

The follow section provides examples of how `error_gens`

are used in practice

## DepolarGen¶

The `DepolarGen`

class is used to represent the symmetric depolarizing channel, which is commonly studied in QEC. For single-qubit gates, this class is used to apply errors at probability \(p\) from set \(\{X, Y, Z\}\). For two-qubit gates, errors also occur with probability \(p\) but errors are chosen uniformally from the set \(\{I, X, Y, Z\}^{\otimes 2} \; \setminus \; I\otimes I\). Errors are always applied after ideal gates except for measurements. In which case, the errors are applied before.

An example of creating an instance of `DepolarGen`

is seen here:

```
>>> import pecos as pc
>>> depolar = pc.error_gens.DepolarGen(model_level='code_capacity', has_idle_errors=False, perp_errors=True)
```

The `model_level`

keyword is used to specify to what set of gates the `DepolarGen`

is applied to. If `model_level`

is set to the value of `'code\_capacity'`

, then the error model is applied before each `LogicalInstruction`

to each data qubits as if these qubits are acted on by `'I'`

. The error model is not applied to any other circuit element. If `model_level`

is set to the value `'phenomenological'`

, then the error model applied to data qubits before each `LogicalInstruction`

as well as to any measurement. If `model_level`

is set to the value `'circuit'`

, then the error model is applied to all the gates in the `QuantumCircuit`

. The default value of `model_level`

is `'circuit'`

.

The `has_idle_errors`

is a keyword that is only relevant when `model_level == 'circuit'`

. If `has_idle_errors`

is set to `True`

, then the error model is applied to inactive qubits as if the qubit is acted on by `'I'`

. If `has_idle_errors`

is set to `False`

, then this does not occur. The default value of `has_idle_errors`

is `True`

.

If the `perp_errors`

keyword is set to `True`

, then errors that are applied to Pauli-basis initializations and measurements are errors that do not include the Pauli-basis of the initializations or measurements. So, for example, \(Z\) is not applied as an error to the `'init |0>'`

operation. If the `perp_errors`

keyword is set to `False`

, then there is no restriction to the errors. The default value of `perp_errors`

is `True`

.

An example of applying an error model using `DepolarGen`

to a `LogicalCircuit`

is seen in the following:

```
>>> depolar = pc.error_gens.DepolarGen(model_level='code_capacity')
>>> surface = pc.qeccs.Surface4444(distance=3)
>>> logic = pc.circuits.LogicalCircuit()
>>> logic.append(surface.gate('ideal init |0>'))
>>> logic.append(surface.gate('I'))
>>> circ_runner = pc.circuit_runners.Standard(seed=1)
>>> state = circ_runner.init(surface.num_qudits)
>>> meas, err = circ_runner.run_logic(state, logic, error_gen=depolar, error_params={'p': 0.1})
```

Note that the keyword argument `error_params`

is used to pass a dictionary that indicates the probability \(p\) of the depolarizing error model.

The values returned by the `run_logic`

method is recorded in the variables `meas`

and `err`

. These variables are dictionaries that record the measurement output and applied errors.

An example of measurement outcomes is given here:

```
>>> # Following the previous example.
>>> meas # doctest: +SKIP
{(1, 0): {7: {9: 1, 11: 1}}}
```

Here, in the last line, we see the measurement outcome. The key of the outer dictionary is a tuple where the first element is the tick index of the `LogicalGate`

and the second element is an index corresponding to a `LogicalInstance`

. That is, the tuple records at what point in the `LogicalCircuit`

was the measurement made. The value of the outer dictionary is just the measurement-outcome dictionary of a `QuantumCircuit`

.

We can see the errors that were generated by the `DepolarGen`

in these lines:

```
>>> # Following the previous example.
>>> err # doctest: +SKIP
{(1, 0): {0: {'after': QuantumCircuit([{'X': {4}, 'Z': {10}}])}}}
```

In the above Listing, we see a dictionary that stores what errors were applied to the `LogicalCircuit`

. The key of the outer dictionary, once again, is a tuple indicating the tick of a `LogicalGate`

and the index of a `LogicalInstance`

. The key of the next inner dictionary is `QuantumCircuit`

tick when the error occurred. The key `'after'`

of the next inner dictionary indicates that the errors are applied after ideal gates. The key `'before'`

is used when indicating that errors are applied before gates. The values of both the `'after'`

and `'before'`

keys are `QuantumCircuits`

. These circuits are the errors that are applied.

The data structure used to describe the errors that are applied to a `LogicalCircuit`

can be directly supplied to a `run_logic`

method of a `circuit_runner`

. Doing so will cause the `run_logic`

method to apply the given error to a `LogicalCircuit`

. This can be seen in the following:

```
>>> # Continuing the previous examples.
>>> logic2 = pc.circuits.LogicalCircuit()
>>> logic2.append(surface.gate('ideal init |+>'))
>>> logic2.append(surface.gate('I'))
>>> state2 = circ_runner.init(surface.num_qudits)
>>> meas2, err2 = circ_runner.run_logic(state2, logic2, error_circuits=err)
```

One use for this is to apply the same error to a different logical basis-state. Doing so allows one to determine if a logical error occurs for the logical operations that stabilizer the basis state.

Note that the `circuit_runners`

currently only apply errors to `LogicalCircuits`

and not to `QuantumCircuits`

.

Todo

Discuss the leakage error model when it is verified…