Stim circuits & sampling
Parse and sample a Stim program
The snippet below prepares a GHZ-2 state and tallies the (q₀, q₁) outcomes over 200 shots.
docs/examples/stim_sampling.py tested from collections import Counter
from ppvm import StimProgram, sample_stim
# A two-qubit GHZ-preparation followed by measurement on both qubits.
prog = StimProgram.parse(
"""
H 0
CX 0 1
M 0 1
"""
)
shots = sample_stim(prog, n_qubits=2, num_shots=200, seed=42)
# Each shot is a list of MeasurementResult; cast to int for tallying.
patterns = Counter(tuple(int(r) for r in shot) for shot in shots)
for pattern, count in sorted(patterns.items()):
print(f"{pattern}: {count}")
# → (0, 0): 102
# → (1, 1): 98
# A GHZ state should only produce (0, 0) or (1, 1) — never (0, 1) or (1, 0).
correlated_fraction = sum(c for p, c in patterns.items() if p[0] == p[1]) / len(shots)
print(f"correlated fraction: {correlated_fraction}") # → correlated fraction: 1.0
Loss-aware measurement results
Every shot is a list of MeasurementResult values:
ZERO, ONE, or LOST when an
atom has been lost. Loss is first-class, so you can model
neutral-atom hardware effects without leaving the Stim flow.
The mathematical background for how loss is represented internally — the extended five-symbol Pauli basis and the channel mappings — is covered in § 5 Loss channel details.
Where to go next
Stim is convenient when you already have a circuit description in that grammar. When you'd rather build the circuit gate-by-gate from Python — or you need non-Clifford gates the Stim grammar can't express — continue to § 3 Generalized Tableau.