ppvm / Pauli propagation & tableau simulation
Sections
  1. § 1 Install
  2. § 2 Stim circuits & sampling
  3. § 3 Generalized Tableau
  4. § 4 Pauli Propagation
  5. § 5 Loss channel details
  6. § 6 Next steps

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.

On this page
  1. Parse and sample
  2. Measurement results
  3. Where to go next