Getting Started
Install Superfermion and run your first quantum circuit in 5 minutes.
Welcome. This page gets you from zero to a running quantum circuit with gradients.
1. Install
pip install superfermionThat's it. Python 3.10–3.13 on Linux, macOS, or Windows. Pre-built wheels for all three platforms — no Rust toolchain required.
Optional extras
pip install "superfermion[all]" # everything
pip install "superfermion[qml]" # JAX + Flax + Optax
pip install "superfermion[chemistry]" # PySCF for molecular simulation
pip install "superfermion[qpu]" # IBM + AWS Braket SDKs
pip install "superfermion[ml]" # PyTorch + TensorFlow + Cirq2. Verify
import superfermion as sf
print(sf.__version__) # e.g. '0.1.5'3. Build a circuit
import superfermion as sf
import sys
# Unicode diagrams on Windows consoles: reconfigure stdout first
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
# Bell state: entangle two qubits
qc = sf.Circuit(2).h(0).cx(0, 1)
print(qc.draw())
# q0: ── H ── ● ──
# q1: ────── X ──Every gate method returns the circuit — chain as many as you want.
4. Run it
result = sf.run(qc, shots=1024)
print(result.counts) # {'00': ~512, '11': ~512}sf.run() works everywhere — local CPU, GPU, IBM Quantum, IonQ. Same API.
5. Get the quantum state
state = sf.simulate(qc) # returns sf.State (Rust-native)
print(state.numpy()) # [0.707+0j, 0, 0, 0.707+0j]
print(state.entropy()) # 0.0
print(state.purity()) # 1.0sf.State lives in Rust. All methods — expectation(), grad(), sample() — dispatch to compiled Rust.
6. Compute an expectation value
from superfermion import Hamiltonian, PauliString
H = Hamiltonian([PauliString("ZZ", coeff=1.0)])
energy = H.expectation(state.numpy())
print(energy) # 1.0
# Or pass the Rust observable format directly to State:
# state.expectation([([3, 3], 1.0, 0.0)]) # ZZ: 0=I 1=X 2=Y 3=Z (LSB-first)7. Take a gradient
theta = sf.param("theta")
qc = sf.Circuit(1).ry(theta, 0)
state = sf.simulate(qc, params={"theta": 0.5})
obs = [([3], 1.0, 0.0)] # Pauli Z
dag = qc.to_ir() # keep parameters symbolic — .bind() would erase them
grads = state.grad(obs, dag, {"theta": 0.5})
print(grads) # {"theta": -0.479...}The adjoint method computes gradients in one backward pass regardless of parameter count. On 20-qubit SU(2) circuits it is ~77x faster than parameter-shift at 40 parameters and ~73x at 80, because parameter-shift needs two circuit runs per parameter. Full grid and correctness checks: gradient benchmarks.
8. Try a different simulation method
# MPS — for weakly entangled circuits, scales to 200+ qubits
qc_mps = sf.Circuit(8).h(0)
for i in range(7):
qc_mps = qc_mps.cnot(i, i + 1)
result = sf.run(qc_mps, method="mps", bond_dim=64, shots=1024)
print(result.counts) # {'00000000': ~512, '11111111': ~512}
# Stabilizer — for Clifford-only circuits, scales to 1000+ qubits
qc_stab = sf.Circuit(100).h(0)
for i in range(99):
qc_stab = qc_stab.cnot(i, i + 1)
result = sf.run(qc_stab, method="stabilizer", shots=1024)
print(list(result.counts.items())[:2])
# Density matrix — for noisy simulation
qc_noisy = sf.Circuit(1).x(0)
noise = sf.NoiseModel().add_depolarizing(0.01)
result = sf.run(qc_noisy, method="density_matrix", noise_model=noise, shots=0)
print(f"purity = {result.metadata['purity']:.4f}")Where next
Now that you've run your first circuit, dive into the guides:
- Building Circuits — every gate, parameterized circuits, circuit properties
- Running Simulations — devices, methods, noise, results
- Gradients & VQE — 5 gradient methods, VQE optimization
- Hardware Compilation — gate optimization, qubit routing
- API Reference — every class and method
From source (development)
git clone https://github.com/Catstate101/superfermion.git
cd superfermion
pip install maturin
cd crates/sf-bindings && maturin develop --release && cd ../..
pip install -e ".[dev]"