From Stim to Tsim¶
import tsim
import stim
If you have been using Stim, using Tsim should feel very similar. In many cases, replacing stim with tsim should just work.
If you're not yet familiar with Stim, there are lots of resources out there: For example, Stim's getting_started notebook, Craig Gidney's Stim tutorial on YouTube, Google's course on QEC, or this Stim 101 tutorial.
Non-Clifford instructions¶
Tsim extends the Stim text format with the non-Clifford instructions T, T_DAG, R_X, R_Y, and R_Z, U3. Rotation angles are specified in units of π.
c = tsim.Circuit("""
T 0
T_DAG 0
R_X(0.1) 0
R_Y(0.2) 0
R_Z(0.3) 0
U3(0.1, 0.2, 0.3) 0
""")
c.diagram(height=150)
Detector Reference Samples¶
There are a few differences between the two packages. For example, Stim's detector sampler will output results relative to a noiseless reference sample. For example, in the following circuit, detector and observable bits will always be False:
circuit_str = """
X 0
M 0
DETECTOR rec[-1]
OBSERVABLE_INCLUDE(0) rec[-1]
"""
c = stim.Circuit(circuit_str)
stim_sampler = c.compile_detector_sampler(seed=None)
samples = stim_sampler.sample(shots=5, append_observables=True)
print(samples)
[[False False] [False False] [False False] [False False] [False False]]
By default, Tsim reports actual detector and observable bits. To match Stim's behavior, set use_detector_reference_sample=True and use_observable_reference_sample=True. This computes a noiseless reference sample and XORs it with the results.
c = tsim.Circuit(circuit_str)
tsim_sampler = c.compile_detector_sampler(seed=0)
# Without reference sample (default): actual detector/observable values
samples = tsim_sampler.sample(shots=5, append_observables=True)
print("Without reference sample:")
print(samples)
# With reference sample: matches Stim behavior
samples_ref = tsim_sampler.sample(
shots=5,
append_observables=True,
use_detector_reference_sample=True,
use_observable_reference_sample=True,
)
print("\nWith reference sample:")
print(samples_ref)
Without reference sample: [[ True True] [ True True] [ True True] [ True True] [ True True]]
With reference sample: [[False False] [False False] [False False] [False False] [False False]]
Batch size and just-in-time compilation¶
Tsim's samplers also have a batch_size argument, which does not exist in Stim. This parameter controls the number of shots sampled in parallel.
When batch_size is not specified, it is automatically chosen based on available device memory (GPU VRAM or system RAM). To achieve maximum performance on a GPU, you can also set batch_size explicitly.
tsim_sampler.sample(shots=1_000_000, batch_size=100_000)
array([[ True],
[ True],
[ True],
...,
[ True],
[ True],
[ True]], shape=(1000000, 1)) Tsim uses jax just-in-time compilation, which is triggered upon first execution of the sample function. This means that subsequent calls to sample with the same parameters will be faster. Note that recompilation is triggered whenever the batch_size is changed.
Visualization methods¶
Tsim supports a subset of Stim's visualization methods. Since Tsim is based on ZX diagrams, it also provides visualization via pyzx.
c = tsim.Circuit("""
RX 0 1
TICK
T 0
TICK
CNOT 0 1
TICK
U3(0.1, 0.2, 0.3) 1
TICK
M 0 1
""")
c.diagram("timeline-svg", height=150)
c.diagram("timeslice-svg", height=80, rows=1)
c.diagram("pyzx");
It can be interesting to look at the ZX diagram of more advanced Stim programs. For example, the following program measures a qubit and records the flipped measurement outcome. Based on this outcome, an X gate is applied to a different qubit:
tsim.Circuit("""
M !0
CNOT rec[-1] 1
""").diagram("pyzx");
REPEAT instructions are flattened¶
Tsim does not support REPEAT instructions. Any REPEAT instructions will be flattened.
c = tsim.Circuit("""
REPEAT 10 {
T 0
}
""")
c.diagram("pyzx");