# How can I extract actual Pauli error in Stim?

I am using a quantum circuit simulator "Stim" to simulate the logical error probability of color code under circuit-level noise.

In the code capacity noise and the phenomenological noise, the Pauli errors to the data qubits that occur with probability p are kept as a list (this is called actual error), and the information of the actual error is used to perform syndrome measurement, and the error is estimated by decoding from the obtained syndrome (this is called the estimated error). Then, the actual error and the estimated error are XORed, and if the resulting error is a logical operator, it is judged to be a logical error.

Now I want to calculate the logical error probability by the similar procedure with circuit-level noise. In this case, I understand the procedure for obtaining the estimated error, since it is almost the same as the phenomenological noise model, except that the syndrome measurement is performed by a syndrome measurement circuit. However, I do not know how to know the actual error. Simply, I am thinking that it might be possible to determine the actual error by considering what Pauli error generated in the circuit result in at the end of the circuit. Is this correct? Also, is there a function in Stim to realize this and find out the actual error?

You can sort of do this in stim, but it's not well supported. The underlying issue is that the locations of errors within a circuit is actually kinda complex, which makes it not trivial.

Basically what you need to do is to give return_errors=True to stim.CompiledDemSampler.sample and then use stim.Circuit.explain_detector_error_model_errors to find noise channels in the circuit that produce the symptoms corresponding to the returned dem errors.

Here's an example. It's kind of long, which is what I mean by "it's not well supported":

import numpy as np
from typing import List

import stim

# Pick a circuit.
circuit: stim.Circuit = stim.Circuit.generated(
'color_code:memory_xyz',
distance=9,
rounds=10,
before_round_data_depolarization=1e-2,
)

# Derive detector error model data we'll use to get the errors.
dem: stim.DetectorErrorModel = circuit.detector_error_model()
dem_sampler: stim.CompiledDemSampler = dem.compile_sampler()
flat_error_instructions: List[stim.DemInstruction] = [
instruction
for instruction in dem.flattened()
if instruction.type == 'error'
]

# Perform a shot and get the error data.
det_data, obs_data, err_data = dem_sampler.sample(shots=1, return_errors=True, bit_packed=False)
single_shot_err_data = err_data

# Find the corresponding dem errors and convert them to circuit errors.
# Many individual circuits errors can have the exact same symptoms; we ask it to just pick one arbitrarily.
dem_filter = stim.DetectorErrorModel()
for error_index in np.flatnonzero(single_shot_err_data):
dem_filter.append(flat_error_instructions[error_index])
explained_errors: List[stim.ExplainedError] = circuit.explain_detector_error_model_errors(dem_filter=dem_filter, reduce_to_one_representative_error=True)

# Print information about circuit errors that would explain the symptoms seen in the shot.
for err in explained_errors:
rep_loc: stim.CircuitErrorLocation = err.circuit_error_locations

if rep_loc.flipped_measurement is not None:
print("flipped measurement", rep_loc.flipped_measurement, "at time", rep_loc.tick_offset)

tc: stim.GateTargetWithCoords
for tc in rep_loc.flipped_pauli_product:
basis = 'X' if tc.gate_target.is_x_target else 'Y' if tc.gate_target.is_y_target else 'Z'
print("flipped", basis, "of qubit with coord", tc.coords, "at time", rep_loc.tick_offset)


which outputs something like:

flipped X of qubit with coord [10.0, 2.0] at time 1
flipped X of qubit with coord [9.0, 4.0] at time 1
flipped Y of qubit with coord [1.5, 3.0] at time 9
flipped Y of qubit with coord [7.0, 10.0] at time 9
flipped Y of qubit with coord [6.0, 10.0] at time 41
flipped Y of qubit with coord [8.5, 5.0] at time 49
flipped Y of qubit with coord [7.0, 6.0] at time 57

• Thank you very much. Your code appears to be one that allows me to know the individual errors that occur in the circuit, but can I know the errors that result from those errors being propagated by the gate and consequently acting on the data qubits after completing the syndrome measurement?
– lan
Apr 17 at 2:30
• @jorge You can use stim.PauliString.after to move errors around. But you're really starting to get into very detailed manipulations. Apr 17 at 3:04
• The Stim instruction says that if it's a circuit, the circuit can't have noise or measurements, so it would be difficult to achieve what I want to achieve using stim.PauliString.after. If it is difficult to know the actual error like this, how do we usually determine if the error correction by estimated error results in a logical error when we simulate QEC using Stim?
– lan
Apr 17 at 3:51
• @jorge The dev version of stim relaxes several of those constraints. Apr 17 at 4:15