# 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 = pc.simulators.SparseSim(surface.num_qudits)
>>> meas, err = circ_runner.run(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`

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 code block, 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`

method of a `circuit_runner`

. Doing so will cause the `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 = pc.simulators.SparseSim(surface.num_qudits)
>>> meas2, err2 = circ_runner.run(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`

can apply errors to both `LogicalCircuits`

and `QuantumCircuits`

.

Todo

Discuss the leakage error model when it is verified…