Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/quantumlib/Stim/llms.txt

Use this file to discover all available pages before exploring further.

stim.DetectorErrorModel (DEM) describes a quantum error correction code as an explicit list of independent error mechanisms, each of which flips a specific set of detectors and logical observables with some probability. It is the primary interface between Stim and matching-based decoders such as PyMatching. A DEM is produced from a circuit via circuit.detector_error_model() and can also be constructed directly from its text format.

Constructor

Creates a DetectorErrorModel from DEM format text, or an empty model if no text is provided.
def __init__(self, detector_error_model_text: str = '') -> None
import stim

dem = stim.DetectorErrorModel('''
    error(0.1) D0
    error(0.1) D0 D1 L0
    error(0.1) D1 D2
    error(0.1) D2
''')
print(len(dem))  # 4
Reads a DEM from a .dem file or file-like object.
@staticmethod
def from_file(
    file: Union[io.TextIOBase, str, pathlib.Path],
) -> stim.DetectorErrorModel
import stim

dem = stim.DetectorErrorModel.from_file("my_circuit.dem")

Iterating instructions

A DetectorErrorModel can be iterated to access its top-level instructions and repeat blocks. Each item is either a stim.DemInstruction or a stim.DemRepeatBlock.
import stim

dem = stim.DetectorErrorModel('''
    error(0.1) D0 D1
    error(0.1) D1 L0
    repeat 100 {
        error(0.05) D0 D1
        shift_detectors 1
    }
    logical_observable L0
''')

for item in dem:
    if isinstance(item, stim.DemRepeatBlock):
        print(f"repeat {item.repeat_count} {{ ... }}")
    else:
        print(f"{item.type}  {item}")
Only top-level instructions are yielded. Instructions inside repeat blocks are accessed through block.body_copy().

DemInstruction types

Type stringDescription
"error"An error mechanism with probability and targets
"detector"Declares a detector (optional coordinate annotation)
"logical_observable"Declares a logical observable
"shift_detectors"Shifts the detector index offset

stim.DemInstruction

Represents a single instruction in a detector error model.
Returns the instruction type as a string: "error", "detector", "logical_observable", or "shift_detectors".
@property
def type(self) -> str
import stim

inst = stim.DetectorErrorModel("error(0.1) D0 D1")[0]
inst.type   # "error"
Returns the instruction’s numeric arguments (e.g. the error probability).
def args_copy(self) -> List[float]
import stim

inst = stim.DetectorErrorModel("error(0.125) D0 L2")[0]
inst.args_copy()   # [0.125]
Returns a copy of the instruction’s targets as a list of stim.DemTarget objects.
def targets_copy(self) -> List[stim.DemTarget]
import stim

inst = stim.DetectorErrorModel("error(0.125) D0 L2")[0]
targets = inst.targets_copy()
# [stim.DemTarget('D0'), stim.DemTarget('L2')]
Returns the targets split into groups separated by ^ separators. Used when decompose_errors=True was specified; each group is one component of the decomposed error.
def target_groups(self) -> List[List[stim.DemTarget]]
import stim

dem = stim.DetectorErrorModel("error(0.1) D0 D1 ^ D2 D3")
groups = dem[0].target_groups()
# [[D0, D1], [D2, D3]]
Returns the optional string tag attached to the instruction.
@property
def tag(self) -> str

stim.DemRepeatBlock

Represents a repeat N { ... } block in a detector error model.
@property
def repeat_count(self) -> int
Returns the body of the repeat block as a stim.DetectorErrorModel.
def body_copy(self) -> stim.DetectorErrorModel
import stim

dem = stim.DetectorErrorModel('''
    repeat 100 {
        error(0.1) D0 D1
        shift_detectors 1
    }
''')
block = dem[0]
print(block.repeat_count)   # 100
print(block.body_copy())    # DetectorErrorModel with 2 instructions
@property
def type(self) -> str  # always "repeat"
Exists for duck-typing convenience: both DemInstruction and DemRepeatBlock expose .type.

stim.DemTarget

Represents a single target in a DEM instruction: a relative detector ID (D5), a logical observable ID (L2), or a separator (^).
# Parse from string
stim.DemTarget("D5")   # relative detector id 5
stim.DemTarget("L2")   # logical observable id 2
stim.DemTarget("^")    # separator

# Factory methods
stim.DemTarget.relative_detector_id(5)     # D5
stim.DemTarget.logical_observable_id(2)    # L2
stim.DemTarget.separator()                 # ^
Returns True if this target is a relative detector ID (prefixed by D in DEM text).
def is_relative_detector_id(self) -> bool
import stim

stim.DemTarget("D3").is_relative_detector_id()   # True
stim.DemTarget("L2").is_relative_detector_id()   # False
stim.DemTarget("^").is_relative_detector_id()    # False
Returns True if this target is a logical observable ID (prefixed by L).
def is_logical_observable_id(self) -> bool
import stim

stim.DemTarget("L2").is_logical_observable_id()   # True
stim.DemTarget("D3").is_logical_observable_id()   # False
Returns True if this target is the ^ separator between error decomposition components.
def is_separator(self) -> bool
Returns a DemTarget representing a relative detector with the given index.
@staticmethod
def relative_detector_id(index: int) -> stim.DemTarget
import stim

m = stim.DetectorErrorModel()
m.append("error", 0.25, [stim.DemTarget.relative_detector_id(13)])
print(repr(m))
# stim.DetectorErrorModel('''
#     error(0.25) D13
# ''')
Returns the integer index stored in the target (the number after D or L).
@property
def val(self) -> int
stim.DemTarget("D5").val   # 5
stim.DemTarget("L6").val   # 6

Arithmetic

Concatenates two DEMs, producing a new model with all instructions from both.
def __add__(self, second: stim.DetectorErrorModel) -> stim.DetectorErrorModel
def __iadd__(self, second: stim.DetectorErrorModel) -> stim.DetectorErrorModel
import stim

m1 = stim.DetectorErrorModel("error(0.1) D0")
m2 = stim.DetectorErrorModel("error(0.2) D1")
combined = m1 + m2
Wraps the DEM contents into a repeat block.
def __mul__(self, repetitions: int) -> stim.DetectorErrorModel
def __imul__(self, repetitions: int) -> stim.DetectorErrorModel
import stim

m = stim.DetectorErrorModel('''
    error(0.1) D0 D1
    shift_detectors 1
''')
repeated = m * 100  # repeat 100 { ... }
Returns True if two DEMs are equal up to small perturbations of error probabilities within an absolute tolerance.
def approx_equals(self, other: object, *, atol: float) -> bool
import stim

m1 = stim.DetectorErrorModel("error(0.1) D0")
m2 = stim.DetectorErrorModel("error(0.1001) D0")
m1.approx_equals(m2, atol=0.001)   # True
m1.approx_equals(m2, atol=0.00001) # False

Properties

num_detectors

int — Number of detectors referenced in the model.

num_observables

int — Number of logical observables referenced in the model.

num_errors

int — Number of error instructions (including those inside repeat blocks).

Sampling

Returns a stim.CompiledDemSampler that can sample detection event and observable flip data directly from the error model, without a circuit.
def compile_sampler(
    self,
    *,
    seed: object = None,
    held_in_memory: bool = False,
) -> stim.CompiledDemSampler
import stim

dem = stim.DetectorErrorModel('''
    error(0.1) D0 D1 L0
    error(0.1) D1 D2
    error(0.1) D2
''')
sampler = dem.compile_sampler()
dets, obs = sampler.sample(shots=1000, separate_observables=True)
# dets.shape == (1000, 3), dtype=bool_
# obs.shape  == (1000, 1), dtype=bool_
Use compiled_detector_sampler() on the original circuit if you want correlated errors to be correctly reproduced. compile_sampler() on a DEM samples errors independently according to the DEM’s stated probabilities.

I/O and utility

Writes the DEM to a file path or file-like object.
def to_file(
    self,
    file: Union[io.TextIOBase, str, pathlib.Path],
) -> None
import stim

dem = stim.DetectorErrorModel("error(0.1) D0 L0")
dem.to_file("my_model.dem")
Returns an equivalent DEM with all repeat blocks expanded inline.
def flattened(self) -> stim.DetectorErrorModel
Returns a copy with all error probabilities rounded to the given number of digits.
def rounded(self, digits: int) -> stim.DetectorErrorModel
Finds the minimum number of graphlike errors needed to produce an undetected logical error.
def shortest_graphlike_error(
    self,
    *,
    ignore_ungraphlike_errors: bool = True,
) -> List[stim.DemInstruction]
import stim

circuit = stim.Circuit.generated(
    "repetition_code:memory",
    rounds=10,
    distance=7,
    before_round_data_depolarization=0.01,
)
dem = circuit.detector_error_model(decompose_errors=True)
errors = dem.shortest_graphlike_error()
print(f"Distance upper bound: {len(errors)}")
Returns the coordinate metadata of detectors in the model as a dictionary from detector index to coordinate list.
def get_detector_coordinates(
    self,
    only: object = None,
) -> Dict[int, List[float]]
Appends an instruction or block to the model.
def append(
    self,
    instruction: object,
    parens_arguments: object = None,
    targets: List[object] = (),
    *,
    tag: str = '',
) -> None
import stim

m = stim.DetectorErrorModel()
m.append("error", 0.25, [
    stim.DemTarget.relative_detector_id(0),
    stim.DemTarget.logical_observable_id(0),
])
m.append("shift_detectors", [], [1])
print(m)

Common workflow

import stim

# 1. Build and annotate a circuit
circuit = stim.Circuit.generated(
    "surface_code:rotated_memory_x",
    distance=5,
    rounds=10,
    after_clifford_depolarization=0.001,
)

# 2. Convert to DEM for a matching decoder
dem = circuit.detector_error_model(decompose_errors=True)
print(f"Detectors: {dem.num_detectors}")
print(f"Error mechanisms: {dem.num_errors}")

# 3. Inspect error terms
for item in dem:
    if hasattr(item, 'type') and item.type == "error":
        prob = item.args_copy()[0]
        targets = [str(t) for t in item.targets_copy() if not t.is_separator()]
        print(f"p={prob:.4f}  targets={targets}")
        break  # just show the first one

# 4. Sample detection events for the decoder
sampler = circuit.compile_detector_sampler()
det_events, obs_flips = sampler.sample(shots=10_000, separate_observables=True)

Build docs developers (and LLMs) love