Trotter-Suzuki product-formula Hamiltonian simulation, approximating e^{-iHt} via structured short-time exponential products with controllable order and step count.
Resources
1Install
npx skillscat add unitarylab/quantum-skills/trotter Install via the SkillsCat registry.
One-Step Run Example Command
python ./scripts/algorithm.pyTrotter-Suzuki Hamiltonian Simulation Skill Guide
Overview
Trotter-Suzuki approximates matrix exponential evolution
$$
U(t) = e^{-iHt}
$$
by decomposing the Hamiltonian into Pauli terms and replacing the full exponential with structured products of easier exponentials.
Key Insight
You do not implement $e^{-i(H_1 + H_2 + \cdots + H_L)t}$ directly. Instead, you build a repeated short-time product formula over terms $H_\ell$, and increase accuracy by:
- Using more time slices.
- Using higher even Suzuki order.
Why Trotter-Suzuki Matters:
- It is the most direct gate-level baseline for Hamiltonian simulation.
- It provides explicit control over accuracy versus circuit depth.
- It works naturally with Pauli-string decompositions.
- It is a strong reference implementation to benchmark advanced methods.
Real Applications:
- Time evolution of spin models and lattice Hamiltonians.
- Digital quantum simulation in chemistry and materials.
- Baseline for comparing QDrift, Taylor-LCU, and QSP methods.
- Teaching and validating decomposition strategies in small systems.
Learning Objectives
After using this skill, you should be able to:
- Explain first-order versus even higher-order Suzuki formulas.
- Understand how order and steps change error and depth.
- Use the repository
SuzukiTrotterAlgorithmclass correctly for experiments. - Extract the circuit from the result dictionary.
- Build reproducible comparisons across parameter sweeps.
Prerequisites
Essential knowledge:
- Hermitian Hamiltonians and unitary time evolution.
- Pauli-string decomposition basics.
- Quantum circuit composition and gate-sequence interpretation.
Mathematical comfort:
- Matrix norms, especially spectral norm.
- Exponential of operators and series intuition.
- Asymptotic error behavior with step refinement.
Using the Provided Implementation
Quick Start Example
from unitarylab.algorithms import SuzukiTrotterAlgorithm
# 2-qubit Heisenberg-like Hamiltonian as grouped Pauli terms
# Each group is a list of (pauli_string, coefficient) tuples
grouped_paulis = [
[("ZI", 0.5), ("IZ", 0.5)],
[("XX", 0.3), ("YY", 0.3)],
]
total_time = 1.0
algo = SuzukiTrotterAlgorithm(order=2, reps=1)
result = algo.run(
grouped_paulis=grouped_paulis,
total_time=total_time,
backend='torch',
)
print("status:", result['status'])
print(result.get('plot', ''))Core Parameters Explained
Constructor
class SuzukiTrotterAlgorithm:
def __init__(self, order: int = 1, reps: int = 1) -> None:
...| Parameter | Type | Default | Description |
|---|---|---|---|
order |
int |
1 |
Suzuki-Trotter order. Must be 1 or an even integer (2,4,6,...). |
reps |
int |
1 |
Number of repetitions of the Trotter step. |
run() Parameters
def run(self, grouped_paulis, total_time, backend='torch', algo_dir=None):
...| Parameter | Type | Default | Description |
|---|---|---|---|
grouped_paulis |
List[List[Tuple[str, float]]] |
required | Hamiltonian as grouped Pauli terms. Each group is a list of (pauli_string, coefficient) tuples. |
total_time |
float |
required | Evolution time $t$ in $e^{-iHt}$. |
backend |
str |
'torch' |
Simulation backend. |
algo_dir |
str|None |
None |
Output directory for circuit diagrams. |
Return Fields
| Key | Type | Description |
|---|---|---|
status |
str |
'success'. |
circuit |
Circuit |
The assembled Trotter circuit. |
plot |
str |
ASCII art result panel. |
Understanding the Core Components
1) Constructor checks and adaptive step rule
From algorithms/trotter/trotter.py:
if order > 1 and order % 2 == 1:
raise ValueError("Order must be 1 or an even integer.")
self.order = order
self.alpha = np.linalg.norm(H, 2)
self.steps = int(min(max(steps, 5**order * np.power(t * self.target_qubits * self.alpha, 1 + 1.0 / order) * np.power(target_error, -1.0 / order) * 1.5), 1e2))Interpretation:
- Odd order above 1 is explicitly forbidden.
- The code uses spectral norm
alpha = ||H||_2. - Step count uses a heuristic tied to order, norm, time, qubits, and target error.
2) Suzuki recursion engine
From _recurse in algorithms/trotter/trotter.py:
if order == 1:
return decomposition
elif order == 2:
halves = [(p, c / 2) for p, c in decomposition[:-1]]
full = [decomposition[-1]]
return halves + full + list(reversed(halves))
else:
reduction = 1 / (4 - 4 ** (1 / (order - 1)))
outer = 2 * self._recurse(order - 2, [(p, c * reduction) for p, c in decomposition])
inner = self._recurse(order - 2, [(p, c * (1 - 4 * reduction)) for p, c in decomposition])
return outer + inner + outerInterpretation:
- Order-2 uses a symmetric palindrome composition.
- Higher even order uses recursive composition with Suzuki reduction coefficient.
- This construction expands gate count rapidly as order increases.
3) Slice expansion and full-circuit assembly
From _expand and _run:
scaled_decomposition = [(p, c / self.steps) for p, c in decomposition]
one_slice = self._recurse(self.order, scaled_decomposition)
return one_slicedecomposition = self._pauli_decompose(self.H, self.t)
sequence = self._expand(decomposition)
for pauli_str, angle in sequence:
gate = pauli_string_evolution(pauli_str, angle)
qc.append(gate, range(self.target_qubits))
self._circuit = qc.repeat(self.steps)
self._evolution_result = self._circuit.get_matrix()Interpretation:
- One slice uses coefficients divided by
steps. - Slice is then repeated by
qc.repeat(self.steps). - Evolution matrix comes directly from the assembled gate sequence.
4) Notes on external package functions (brief)
_pauli_decomposeis inherited fromHamiltonianSimulationResult; it handles banded-real optimization and generic decomposition.pauli_string_evolutionbuilds the circuit for a single Pauli-string exponential.total_erroris computed in the base class by comparing toscipy.linalg.expm(-1j * H * t).
Hands-On Example: Hamiltonian Simulation
Use a parameter sweep to visualize tradeoffs.
from unitarylab.algorithms import SuzukiTrotterAlgorithm
# 2-qubit Hamiltonian as grouped Pauli terms
grouped_paulis = [
[("ZI", 0.5), ("IZ", -0.3)],
[("XX", 0.2), ("YY", 0.2), ("ZZ", 0.1)],
]
for order in [1, 2, 4]:
algo = SuzukiTrotterAlgorithm(order=order, reps=1)
result = algo.run(
grouped_paulis=grouped_paulis,
total_time=1.0,
backend='torch',
)
print(f"order={order}, status={result['status']}")
print(result.get('plot', ''))What to look for:
- Higher order produces more complex circuits but better approximation.
- The
plotfield provides a summary of the decomposition.
Mathematical Deep Dive
Assume local decomposition:
$$
H = \sum_{j=1}^{N} h_j H_j
$$
and non-commuting terms satisfy
$$
e^{-i(H_1+H_2)t} \neq e^{-iH_1t}e^{-iH_2t}.
$$
The Lie-Trotter product limit gives:
$$
e^{-i(H_1+H_2)t} = \lim_{r\to\infty}\left(e^{-iH_1 t/r}e^{-iH_2 t/r}\right)^r.
$$
For $\Delta t=t/r$, first-order and second-order product formulas are:
$$
S_1(\Delta t) = \prod_{\ell=1}^{L} e^{-iH_\ell \Delta t}
$$
$$
S_2(\Delta t)=\left(\prod_{\ell=1}^{L-1}e^{-iH_\ell\Delta t/2}\right)e^{-iH_L\Delta t}\left(\prod_{\ell=L-1}^{1}e^{-iH_\ell\Delta t/2}\right).
$$
Higher even-order Suzuki recursion can be written as:
$$
S_{2k+2}(t)=\left(S_{2k}(p_k t)\right)^2 S_{2k}((1-4p_k)t)\left(S_{2k}(p_k t)\right)^2,
\quad
p_k=\left(4-4^{1/(2k+1)}\right)^{-1}.
$$
Equivalent implementation form in this code is:
$$
S_{2k}(\Delta t)=S_{2k-2}(p_k\Delta t)^2,S_{2k-2}((1-4p_k)\Delta t),S_{2k-2}(p_k\Delta t)^2.
$$
Error expressions (local step error and global error) follow the standard scaling:
$$
\varepsilon_{\Delta t}^{(1)} \sim O(|H|^2\Delta t^2),
\quad
\varepsilon_{t}^{(1)} \sim O(|H|^2 t\Delta t)
$$
$$
\varepsilon_{\Delta t}^{(2)} \sim O(|H|^3\Delta t^3),
\quad
\varepsilon_{t}^{(2)} \sim O(|H|^3 t\Delta t^2)
$$
$$
\varepsilon_{\Delta t}^{(2k)} \sim O(|H|^{2k+1}\Delta t^{2k+1}),
\quad
\varepsilon_{t}^{(2k)} \sim O(|H|^{2k+1} t\Delta t^{2k}).
$$
Implementation-consistent notes:
- Use the notation $\Delta t=t/r$ consistently when reasoning about formulas. In code, this is implemented by first scaling coefficients by
1/self.stepsin_expand, then repeating the one-slice circuit withqc.repeat(self.steps). - The recursive Suzuki coefficient in the code,
reduction = 1 / (4 - 4 ** (1 / (order - 1))),
is the same structure as the standard recursive coefficient $p_k$ after index mapping. - Practical behavior may differ from asymptotic formulas when step clamping is active, because the current implementation enforces
self.steps <= 100.
Reference Implementation (PennyLane)
PennyLane provides qml.ApproxTimeEvolution for first-order Trotterized
Hamiltonian time evolution.
Minimal PennyLane Example
import pennylane as qml
n_wires = 2
dev = qml.device("default.qubit", wires=n_wires)
coeffs = [0.1, 0.2, 0.3]
ops = [
qml.Z(0) @ qml.Z(1),
qml.X(0),
qml.X(1),
]
hamiltonian = qml.Hamiltonian(coeffs, ops)
@qml.qnode(dev)
def circuit(t):
qml.ApproxTimeEvolution(hamiltonian, t, n=2)
return [qml.expval(qml.Z(i)) for i in range(n_wires)]
result = circuit(0.5)
print(result)Real-World Applications
- Spin-chain evolution benchmarking.
- Digital simulation baseline for chemistry Hamiltonians.
- Hardware-aware gate budgeting and algorithm comparison.
- Educational demos of deterministic product formulas.