Simulator API
The top-level surface:
from qliff import Simulator, Circuit, PauliString, expectation, fidelity| Name | What it is |
|---|---|
Simulator | The ergonomic, stim-style facade you will use most. |
Circuit | A stim-like IR with noise, detectors and observables — see Noise and Error Correction. |
PauliString, expectation, fidelity | Pauli observables and metrics. |
ColTableau / RowTableau | The native CHP tableau cores Simulator wraps — column-major (fast gates) and row-major (fast measurement). |
__version__ | The package version (sourced from the Rust crate). |
This page documents Simulator.
Simulator
Simulator(num_qubits, seed=None)A Clifford stabilizer simulator. Starts in seed for reproducible measurement sampling.
Gate methods return self, so operations chain:
from qliff import Simulator
print(Simulator(2).H(0).CX(0, 1).canon())
# ['+XX', '+ZZ']Target conventions
- Single-qubit gates accept one or more targets.
sim.X(0, 1, 2)applies the gate to each listed qubit. - Two-qubit gates take flattened
(control, target)pairs.sim.CX(0, 1)is one CX;sim.CX(0, 1, 2, 3)applies CX(0→1) then CX(2→3). An odd number of targets raisesValueError. - Iterables are flattened, so
sim.H([0, 1])works too.
Single-qubit gates
Each returns self. Accepts one or more targets.
| Method | Gate |
|---|---|
H(*q) | Hadamard |
S(*q) | Phase ( |
S_DAG(*q) | Inverse phase ( |
X(*q) | Pauli |
Y(*q) | Pauli |
Z(*q) | Pauli |
from qliff import Simulator
print(Simulator(1).H(0).S(0).canon())
# ['+Y']Two-qubit gates
Each returns self. Takes flattened (control, target) pairs.
| Method | Gate |
|---|---|
CX(*t) | Controlled- |
CNOT(*t) | Alias for CX |
CZ(*t) | Controlled- |
SWAP(*t) | Swap two qubits |
from qliff import Simulator
ghz = Simulator(3).H(0).CX(0, 1, 1, 2)
print(ghz.canon())
# ['+XXX', '+ZZI', '+IZZ']Measurement and reset
| Method | Returns | Description |
|---|---|---|
M(*q) | int or list[int] | Measure in the int; several -> list. Appends to record. |
MR(*q) | int or list[int] | Measure, then reset the measured qubit(s) to $ |
R(*q) | self | Reset qubit(s) to $ |
reset(*q) | self | Alias for R. |
from qliff import Simulator
s = Simulator(2).X(0)
print(s.M(0), s.M(1)) # 1 0
print(s.record) # [1, 0]record
sim.record # -> list[int]Measurement outcomes so far, in order. clear() empties it and returns self.
Inspection
num_qubits
sim.num_qubits # -> intThe number of qubits in the register.
copy()
sim.copy() # -> SimulatorA deep copy with an independent tableau. Useful for probing whether a measurement is deterministic without disturbing the original.
stabilizers()
sim.stabilizers() # -> list[str]The raw (non-canonical) signed-Pauli generators, e.g. '+XX', '-Z'. These depend on the gate history.
canon()
sim.canon() # -> list[str]The canonical signed-Pauli generators: a unique reduced form of the stabilizer group. Two states are equal iff their canonical stabilizers match — so this is the tool for equality checks.
from qliff import Simulator
a = Simulator(2).H(0).CX(0, 1)
b = Simulator(2).H(1).CX(1, 0)
assert a.canon() == b.canon()Observables
Two methods read or measure a Pauli operator PauliString or a signed string like "ZZ" or "-X".
| Method | Returns | Description |
|---|---|---|
peek(P) | 0 if not an eigenstate) | |
measure(P, force=None) | (value, random) | measures value in random flags a coin flip |
bell = Simulator(2).H(0).CX(0, 1)
bell.peek("ZZ") # +1
bell.measure("XX") # (1, False)measure collapses the state and works on multi-qubit stabilizers — the primitive behind syndrome extraction. Pin a random outcome with force=+1/-1.
See Observables & Metrics for PauliString, the expectation free function, and fidelity.