# Where do lines like "error(0.00033) D0 D9 L0 ^ D7 ^ D8" come from in a stim detector error model?

I have a Stim detector error model file derived from a surface code circuit. I'm trying to understand exactly what lines like error(0.00033) D0 D9 L0 ^ D7 ^ D8 from the model file mean.

1. Is the 0.00033 a probability?
2. What's the distinction between L0 and D0?
3. Why are there multiple parts to the error, separated by ^? Is this the X and Z parts of the matching graph?
4. Why is it three parts instead of two?
• Note: got this question privately and wrote a public answer. Commented Jan 23, 2022 at 3:32

[What does error(0.0033) D0 D9 L0 ^ D7 ^ D8 mean?]

It is declaring an error mechanism that occurs 0.33% of the time. When this error occurs, it simultaneously flips detectors 0, 7, 8, and 9 as well as logical observable 0. Furthermore, it is suggested that this error can be thought of as a combination of three simpler errors: one that flips detectors 0 and 9 as well as logical observable 0, one that just flips detector 7, and one that just flips detector 8.

The meanings of these detector and observable indices come from the circuit. Detector 0 is the first DETECTOR instruction in the circuit, detector 1 is the second, etc. The observable indices come from the indices given to OBSERVABLE_INCLUDE instructions.

Is the 0.00033 a probability?

Yes, it's a probability. More specifically, it is an independent probability (as opposed to a disjoint one). Every error specified in the model is independent of the others. Circuit errors that use disjoint probabilities (e.g. two qubit-depolarization DEPOLARIZE2 is normally specified as 15 disjoint cases) have to be converted or approximated as part of producing the model.

What's the distinction between L0 and D0?

D0 is a detection event. It is a visible symptom of the error. In the surface code, it will correspond to a stabilizer measurement changing its value from one round to another.

L0 is an error in an observable, or equivalently a frame change to the observable. It means this error will cause a logical observable's eventual measurement result to be flipped. It is an implied symptom of the error.

Why are there multiple parts to the error, separated by ^? Is this the X and Z parts of the matching graph?

There are multiple parts because this error model was produced with the decompose_errors option set. The decomposition does end up relating to the X and Z connected components of the matching graph, but that's not the whole story.

The error as a whole is D0 D7 D8 D9 L0. So this one error creates 4 detection events. That is a problem for a decoder that wants to represent errors as edges, such as min weight perfect matching decoders and union find decoders. The issue is that edges have degree 2, but this error has degree 4. So it's a hyper edge. Which will confuse the decoder.

What Stim is doing when producing the error model is trying to help the decoder out by suggesting a decomposition of this complex error into "graphlike" errors (errors with at most 2 detection events). Stim is saying: if you don't want to deal with hyper edges, if you only handle graphlike errors, consider breaking this complex error down into the edge D0 -- D9 (with frame change L0), the edge D7 -- boundary and the edge D8 -- boundary. This gives the decoder a lot more freedom in how to process the problematic error; it can do things which are less naive than simply ignoring the error.

Why is it three parts instead of two?

Stim uses two rules when deciding how to decompose errors: the "local" rule, and the "global" rule.

The local rule says: when a single circuit error produces multiple DEM (detector error model) errors (e.g. a DEPOLARIZE2 has 15 cases), aggressively decompose into other DEM errors from the same circuit error. Specifically, if a DEM error has a set of detection events that's equal to the union of detection events from smaller non-overlapping DEM errors from the same circuit error, then suggest decomposing into those cases.

For example, at the corner of a rotated surface code, a Y error on a data qubit will produce a detection event on one X stabilizer and one Z stabilizer. A DEPOLARIZE1 error on this data qubit will produce three DEM errors (one for the X error, one for the Y, and one for the Z). Stim will notice that the Y case's two detection events are equal to the union of the X and Z cases' detection events. So it will suggest decomposing the Y DEM error into the X part and Z part. Note that this occurred even though the DEM error from the Y error was already graphlike. The local rule only cares about explaining big cases in terms of small cases, it doesn't stop just because things have become graphlike.

The global rule says: when the local rule fails to turn a DEM error into graphlike parts, try to pull parts off of it that are errors from elsewhere in the model. Sometimes there's more than one choice of how to do this, so things get a bit subjective and there's heuristics for breaking ties. This heuristics can change from version to version. Should you greedily check if any single detection event from the error occurs on its own elsewhere in the model, and then move on to checking if any pair from the error occurs elsewhere... or go in the opposite order? That can matter sometimes. Anyways, the point is that if the local rule produced a DEM error like D0 ^ D1 D2 D3 and there's an error D1 D3 somewhere else in the model, then we could suggest the decomposition D0 ^ D1 D3 ^ D2.

The idea here is that we're desperate and all we really want to do is not pick a decomposition that violates some invariant that's crucial to the function of the error correcting code. For example, it would be disastrous to decompose a surface code Y error into parts that were half-X half-Z, because that violates the "charge conservation rules" that make the surface code work. But if D1 D3 appears on its own elsewhere in the model, surely we can't accidentally break anything by using it as a part. So we do.

[Again] Why is it three parts instead of two?

This is usually because of the local rule aggressively decomposing a DEM error, even when the parts were already graphlike. For example, the two singleton detection events are perhaps the X and Z parts of a Y error on a corner data qubit and the associated pair of detection events is something that occurred together with this Y error (e.g. because the Y data error is actually part of a pair of Pauli errors from a single case of a two-qubit depolarization error).