About this map
Sections
What this is
Quantum algorithms are not written from scratch. They are assembled from a small number of reusable steps, and almost every published method is a different route through the same handful of them.
This is a map of those routes. Circles are the things an algorithm can be holding. Lines are the steps that carry you from one to the next. A method is a path across.
Nothing here is generated. Every line was read out of a paper and checked against it.
How to read it
- Something you can hold — a state, a matrix, a circuit, an answer.
- The same, in the middle of a step you have opened.
- A step. Someone has published a way through it.
- A step whose way through has not been pinned to one method.
- A step nothing published fills yet.
- A step you have opened. What is drawn inside it is how it was done.
- There is a record in the repository for this one.
How to move around
- Two fingers move the map. Pinch to zoom, or hold ctrl and scroll.
- Click a step to open it in place — everything else stays where it is.
- Click a name to read the full record without leaving the map.
- Arrow keys move, plus and minus zoom, zero puts it back.
What a line is claiming
A solid line means a paper puts those two steps together and we have the citation. A long-dashed line means the route is recorded but no single method has been named for that step. A short-dashed line means nothing published fills it — the step is real, the way through is not written yet.
A count after a step's name — ×T/h, ×O(κ) — means the route walks that step that many times rather than once. It is the source's own symbol, and the card says what it stands for and what one turn costs. A step with no count is a step no source we read said is repeated, which is not the same as one taken once.
A line drawn nested under another, on the soft shaded band behind it, is a narrower version of the line above it: the same construction, re-analysed or re-tuned, filling the same step. It is why two lines can draw the identical interior and still be two entries. Lines outside the band are alternatives to their neighbours, not versions of them.
The map does not hide the gaps. An empty step is drawn as an empty step.
What is not here yet
The map covers the algorithm literature. The repository covers circuits and primitives. They overlap less than you would expect, and where a method has no record we say so on its page rather than leaving the space blank.
Where something named here does have a record, its name links straight to it.
Method
Product-formula (Trotter-Suzuki) simulation
Split into terms that can each be exponentiated directly and alternate short evolutions of them — the Lie-Trotter formula and its higher-order generalizations. No block-encoding is built and there is no all-zeros flag to amplify.
Open the full recordFills the slot: Simulate Hamiltonian evolution
Needs a decomposition of into efficiently exponentiable summands. The error is governed by commutators among those summands: Childs, Su, Tran, Wiebe and Zhu's analysis "directly exploits the commutativity of operator summands, producing tighter error bounds for both real- and imaginary-time evolutions", and they show local observables can be simulated with complexity independent of the system size for power-law interacting systems. Term ordering affects the error and is not fixed by the formula itself.
An access model for — a sum of efficiently exponentiable terms, sparse-access oracles, or a block-encoding — plus an evolution time and a target error .
Hamiltonian you can query → Circuit for e^{-iHt}alternate exponentials of each term
The single exponential of is replaced by a product of exponentials of its terms. The first-order formula fixes an ordering and alternates them, approximation: the joint exponential of the sum becomes the product of the separate ones, discarding the cross terms that non-commuting produce; higher orders are built recursively as with . Writing the additive error as , it is bounded by nested commutators: with . assumption: that clean form is the one stated for anti-Hermitian — times a physical Hermitian term — the general case carrying a further exponential factor. A circuit for time applies times, and suffices for error .
approximationassumption
A circuit approximating to within , with a stated query or gate count, an ancilla count, and the norm parameter — sparsity times , or the LCU 1-norm — that the cost is measured against.
None found yet.
given H = sum_j H_j with each H_j efficiently exponentiable,
evolution time t, step count r, h = t/r
for step = 1 ... r:
# first order (Lie-Trotter): one short evolution per summand, in order
for j = 1 ... m: apply exp(-i h H_j)
# higher order: the same summands in the symmetrised sub-step sequence
# of the chosen Suzuki formula
# no block-encoding is built, and there is no all-zeros flag to amplify
# the error is governed by commutators among the summands, and the term
# order affects it -- the formula itself does not fix that orderIn the sparse-access oracle model, Berry, Ahokas, Cleve and Sanders: when acts on qubits, has at most a constant number of nonzero entries in each row/column, and is bounded by a constant, one may select any positive integer such that the simulation requires accesses to matrix entries of . They also show the temporal scaling cannot be significantly improved beyond this, because sublinear time scaling is not possible.
None found yet.
The precision dependence is the weak point, and it is what the later families were built to fix: Berry, Childs, Cleve, Kothari and Somma's truncated-Taylor method has a cost depending logarithmically on the inverse of the desired precision, which the authors state is optimal. That does not make product formulas obsolete — the commutator bounds above often win on constants and on structured systems, and there is no ancilla overhead — but a high-precision cost model that quotes only a product formula has picked the wrong family.
Qiskit's product-formula evolution synthesis (LieTrotter and SuzukiTrotter)
About
IBM's Qiskit ships product formulas not as circuits but as synthesis strategies plugged into one gate. `PauliEvolutionGate` is documented as the "Time-evolution of an operator consisting of Paulis": for a Hermitian consisting of Pauli terms and real evolution time , "this gate represents the unitary" . The release note that introduced it states the separation outright — "The synthesis of this gate is performed by `EvolutionSynthesis` and is decoupled from the gate itself" — and the gate's own docstring gives the reason for it: "This gate represents the exact evolution . Implementing this operation exactly, however, generally requires an exponential number of gates. The compiler therefore typically implements an *approximation* of the unitary , e.g. using a product formula such as defined by `LieTrotter`." The gate and three strategies arrived together in Qiskit 0.19, whose release note lists them as `LieTrotter`, "first order Trotterization"; `SuzukiTrotter`, "higher order Trotterization"; and `MatrixExponential`, "exact, matrix-based evolution". Only the first two are product formulas.
Methods
`LieTrotter` is not a separate construction: it subclasses `SuzukiTrotter` and calls `super().__init__(1, ...)`, so first order is the order-1 case of the same recursion. That recursion is `SuzukiTrotter._recurse(order, grouped_paulis)`. At order 1 it returns the groups untouched. At order 2 it halves the coefficients of every group but the last and returns `halves + full + list(reversed(halves))` — the last summand at full time between two mirrored halves. Above that it sets `reduction = 1 / (4 - 4 ** (1 / (order - 1)))`, which is the coefficient this record's hop writes for a formula of order , and returns `outer + inner + outer`, where `outer` is the expansion of order at `reduction` taken twice and `inner` is the same expansion at `1 - 4 * reduction`. Odd orders above 1 are refused in the constructor: "Suzuki product formulae are symmetric and therefore only defined for when the order is 1 or even". `expand` returns the sequence as `(pauli, indices, angle)` triples with the angle `coeff * time * 2 / self.reps`, the docstring warning that "the rotation angle contains a factor of 2". By default each Pauli term becomes its own non-commuting factor, and the source says so against itself — "Assume no commutativity here. If we were to group commuting Paulis, here would be the location to do so." — a caller wanting grouping passes a list of operators whose terms already commute. The term ordering this record's `conditions` says the formula does not fix is exposed as `preserve_order`: set to `False`, `reorder_paulis` builds a graph joining any two terms that "act on the same qubit", colours it with rustworkx's `graph_greedy_color` under `ColoringStrategy.Saturation`, and emits terms colour by colour so that same-colour subcircuits "can be run in parallel". It is documented as "deterministic and invariant under permutation of the Pauli term in ``paulis``". Two further knobs are gate-level rather than formula-level: `cx_structure`, `"chain"` for "next neighbor connections" or `"fountain"` where "all qubits are connected to one", and `insert_barriers`.
Data
Nothing in the repository runs the module on a physical system; what exercises it is `test/python/circuit/library/test_evolution_gate.py`. `test_lie_trotter` and `test_suzuki_trotter` both evolve `(X ^ X ^ X) + (Y ^ Y ^ Y) + (Z ^ Z ^ Z)` for `time = 0.123` with `reps = 4` — the first at first order, the second at orders 2, 4 and 6 — and assert CX counts derived from the recursion depth, the test's own comment reading "recurse (order - 2) / 2 times, base case has 5 blocks with 4 CX each". `test_suzuki_trotter_manual_no_reorder` evolves `X + Y` on one qubit at order 4 against a circuit built by hand from `p_4 = 1 / (4 - 4 ** (1 / 3))`, commented "coefficient for reduced time from Suzuki paper". `test_suzuki_trotter_manual` evolves `(X ^ X ^ I ^ I) + (I ^ Y ^ Y ^ I) + (I ^ I ^ Z ^ Z)` at order 2 with `preserve_order = False` and asserts an exact five-gate circuit. The accuracy helper is narrower than it looks: `assertSuzukiTrotterIsCorrect` compares the synthesised circuit against a `SuzukiTrotter` of the same `order` and `reps` built with an `exact_atomic_evolution`, so it checks that the decomposition reproduces the product formula, not that the product formula is close to . `scipy.linalg.expm` does appear in six of that file's tests, but wherever a product-formula circuit is the thing compared against it, the instance is one on which the formula carries no error: `test_global_phase` binds the default-synthesis `evo.definition` and asserts equality with `expm` under its own stated condition, "since all terms in the Pauli operator commute, we can compare to an exact matrix exponential". `test_matrix_decomposition` runs two subtests and neither exercises the recursion — the first synthesises with `MatrixExponential`, and the second calls `PauliEvolutionGate.to_matrix()`, which is itself `sc.sparse.linalg.expm(-1j * time * spmatrix)` on the operator and never consults the synthesis. The one test that measures an approximation against `expm` is `test_qdrift_evolution`, and its subject is `QDrift`. The largest instance named anywhere is not in the tests but in the Qiskit 1.3 release note: a 100-qubit Heisenberg Hamiltonian with 10 timesteps at fourth order. No molecule, lattice or device is named.
Code
The module is `qiskit/synthesis/evolution/` in https://github.com/Qiskit/qiskit, Apache License 2.0. `product_formula.py` holds the `ProductFormula` base and `reorder_paulis`, `suzuki_trotter.py` the recursion, `lie_trotter.py` the order-1 subclass; beside them sit `qdrift.py` (Campbell's randomised `QDrift`, a different construction), `matrix_synthesis.py` (`MatrixExponential`), `evolution_synthesis.py` and `pauli_network.py`. Seven of the directory's eight Python files are headed "(C) Copyright IBM 2021"; the eighth, `pauli_network.py`, is headed "(C) Copyright IBM 2024". The gate is `qiskit/circuit/library/pauli_evolution.py`, and with no `synthesis` argument it constructs `LieTrotter()` — first order, one repetition. `ProductFormula.synthesize` has two paths. With `wrap=True` or a caller-supplied `atomic_evolution` it goes through `_custom_evolution`, where those two cases are themselves disjoint: given a custom `atomic_evolution` the loop builds a `SparseObservable` for each Pauli rotation and calls `self.atomic_evolution(circuit, operator, time=1)`, appending whatever the caller's function queues and creating no gate object of its own; only the other branch, commented "this means self._wrap is True", builds each Pauli's circuit Rust-side and wraps it with `evo.to_gate(label=f"exp(it {pauli_string})")`. Otherwise the whole network is built Rust-side in one call through `from qiskit._accelerate.circuit_library import pauli_evolution`. Since Qiskit 1.3 the transpiler reaches all of it through high-level-synthesis plugins in `qiskit/transpiler/passes/synthesis/hls_plugins.py`. The second of those, `PauliEvolutionSynthesisRustiq`, is not an alternative product formula: it calls `algo.expand(evo)` on the same `ProductFormula`, warns "Cannot apply Rustiq if the evolution synthesis does not implement ``expand``", and differs only in how the resulting Pauli network becomes gates. Read at tag 2.5.2, released 2026-08-13. The same recursion also exists in Rust at `crates/synthesis/src/evolution/suzuki_trotter.rs`, where the coefficient is written `1.0 / (4.0 - 4_f64.powf(1.0 / (order as f64 - 1.0)))`, reached from `crates/circuit_library/src/suzuki_trotter.rs`.
Results
One number is reported for this module and it is a construction time, not an accuracy and not a gate count. The Qiskit 1.3 release note says the default plugin "constructs circuit as before, but faster as it internally uses Rust", that "the larger the circuit (e.g. by the Hamiltonian size, the number of timesteps, or the Suzuki-Trotter order), the higher the speedup", and gives a single instance: "a 100-qubit Heisenberg Hamiltonian with 10 timesteps and a 4th-order Trotter formula is now constructed ~9.4x faster". The baseline is named only as constructing "as before", no machine is stated, and the quantity measured is the time to build the circuit rather than to run it. The other quantities the repository pins are exact circuit contents, not measurements: the order-2 expansion of `H = IX + ZZ` at one repetition is documented as `("X", [0], t), ("ZZ", [0, 1], 2t), ("X", [0], t)`, and the four-qubit reordering test fixes the output to `rzz(time, 0, 1)`, `rxx(time, 2, 3)`, `ryy(2 * time, 1, 2)`, `rxx(time, 2, 3)`, `rzz(time, 0, 1)`.
PennyLane's TrotterProduct operation
About
Xanadu's PennyLane ships the same family as a single operation rather than as a compiler strategy. `TrotterProduct` arrived in v0.33.0, added by pull request 4661, whose release note introduces it as "Higher-order Trotter-Suzuki methods are now easily accessible through a new operation called `TrotterProduct`" and tells the caller: "Simply specify the `order` of the approximation and the evolution `time`." What makes it worth recording beside the Qiskit module is not the recursion, which is the same one, but that in the release read here — v0.45.1 — it ships the error analysis with it: there the class is declared `TrotterProduct(ErrorOperation, ResourcesOperation)` and carries an `error()` method returning "an *upper-bound* on the spectral norm error", implemented from the paper this record's `conditions` credits for the commutator bounds. That method is a property of the version read rather than of the operation for all time, and every claim about it below is scoped to v0.45.1.
Methods
The class docstring states the recursion in the same symbols this record's hop uses: symmetrised products "where the coefficient is" , and the -th order, -step approximation . The sign convention is documented opposite to Qiskit's: `time` is "the parameter in " where `PauliEvolutionGate` documents , and the docstring's own way of recovering the older `ApproxTimeEvolution` is `qp.adjoint(qp.TrotterProduct(hamiltonian, time, order=1, n=n))`. In code, `_scalar(order)` returns `(4 - 4**root) ** -1` with `root = 1 / (order - 1)`, and `_recursive_expression` returns `(2 * ops_lst_1) + ops_lst_2 + (2 * ops_lst_1)`. Its order-2 base case is `[Evolution(op, -x * 0.5) for op in ops + ops[::-1]]` — every term at half time forwards then backwards, so the last term appears as two adjacent half-time exponentials of the same operator where Qiskit's `_recurse` emits one at full time; the sequences differ by that merge, not by the formula. Two constraints on the input have no counterpart in Qiskit. The terms need not be Paulis: the argument is documented as "the Hamiltonian written as a linear combination of operators with known matrix exponentials", and the constructor requires a `Sum` (converting a `LinearCombination` or `SProd` first) with at least two terms — "There should be at least 2 terms in the Hamiltonian. Otherwise use `qp.exp`". And `check_hermitian=True` by default verifies every operand. On term order the class does not choose for you and says so in a standing warning: "The Trotter-Suzuki decomposition depends on the order of the summed observables. Two mathematically identical `LinearCombination` objects may undergo different time evolutions due to the order in which those observables are stored" — `compute_decomposition` reads `kwargs["base"].operands` in stored order, where Qiskit optionally recolours it. `error()` offers two bounds, both attributed by section: "one-norm-bound" to "Section 2.3 (lemma 6, equation 22 and 23)" and the default "commutator-bound" to "Appendix C (equation 189)" of Childs et al. (2021), https://arxiv.org/abs/1912.08854. `_one_norm_error` computes `(h_one_norm * t) ** (p + 1) / (math.factorial(p + 1) * n**p)` times `(upsilon ** (p + 1) + 1)`; `_commutator_error` sums nested commutators over every combination of exponents summing to `p`, with prefactor `(2 * upsilon * t ** (p + 1)) / ((p + 1) * n**p)`. Both use = `_compute_repetitions`, documented against "the definition of upsilon from section 2.3 (equation 15)" of the same paper and returning 1 at order 1 and `(5 ** (k - 1)) * 2` otherwise. One qualifier the default hides: `fast=True` replaces each spectral norm with an upper bound — the sum of the absolute Pauli coefficients where the operator has a Pauli representation, otherwise the Frobenius norm — so the number returned by default is a bound computed from bounds.
Data
The documented runs are all small and all in software. The v0.33.0 release note builds `H = qml.dot([0.25, 0.75], [qml.PauliX(0), qml.PauliZ(0)])`, applies a Hadamard and then `qml.TrotterProduct(H, time=2.4, order=2)` on `qml.device("default.qubit", wires=2)`, and returns the state. The `error()` examples use `qp.dot([1.0, 0.5, -0.25], [qp.X(0), qp.Y(0), qp.Z(0)])` at `time=0.01, order=2` and compute a bound rather than running a circuit. The usage-details example is a four-term two-qubit Hamiltonian, `[qp.X(0), qp.Y(1), qp.Y(0) @ qp.Z(1), qp.X(0) @ qp.Y(1)]` with coefficients `[0.5, 0.2, 0.1, -0.6]`, used only to show that grouping the operands changes the decomposition. `default.qubit` is the only device named in the `TrotterProduct` docstring; no dataset, molecule or lattice appears, and no hardware run is reported.
Code
`pennylane/templates/subroutines/time_evolution/trotter.py` in https://github.com/PennyLaneAI/pennylane — Python, Apache License 2.0, headed "Copyright 2018-2023 Xanadu Quantum Technologies Inc." and described in its module docstring as "templates for Suzuki-Trotter approximation based subroutines". The path moved: at v0.33.0, where the class was added, the same file was `pennylane/templates/subroutines/trotter.py`. The two error bounds are not defined in it — the module imports `_one_norm_error` and `_commutator_error` `from pennylane.resource.error` for `error()` to call, and both live in `pennylane/resource/error/trotter_error.py`, which holds nine functions and no classes: those two plus `_compute_repetitions`, `_spectral_norm`, `_generate_combinations`, `_recursive_nested_commutator` and the flattening helpers `_recursive_flatten`, `_simplify` and `_flatten_trotter`. Back in `trotter.py` itself, beneath `TrotterProduct`, sit `TrotterizedQfunc` and the `trotterize` function, which apply the identical recursion to an arbitrary quantum function instead of to a Hamiltonian — the docstring's framing is that a caller supplies "the first order expansion " and the machinery "expands it to any higher order". Read at tag v0.45.1, released 2026-06-26.
Results
What the sources report are documented outputs, not benchmarks. The v0.33.0 release note prints the evolved state for its two-term Hamiltonian as `[-0.13259524+0.59790098j 0. +0.j -0.13259524-0.77932754j 0. +0.j ]`. The `error()` docstring prints, for `qp.dot([1.0, 0.5, -0.25], [qp.X(0), qp.Y(0), qp.Z(0)])` at `time=0.01, order=2`, `SpectralNormError(8.039062500000003e-06)` under `method="one-norm-bound"` and `SpectralNormError(6.166666666666668e-06)` under `method="commutator-bound"` — on that example the commutator bound is the smaller of the two, and it is the method's default. Both are upper bounds computed classically from the operator, not measured errors, and both come from the default `fast=True` path. No gate count, runtime or hardware result is reported for this operation.
Trotter–Suzuki Hamiltonian simulation · Qiskit
From the repository — run, not written up from a paper · native
About
Approximates the time evolution of a Hamiltonian with non-commuting terms by alternating their individual exponentials.
Methods
None found yet.
Data
None found yet.
Code
Qiskit
Results
Construction checked against first-order Trotter formula · exact 1-qubit target state derived by hand
- Trotter–Suzuki Hamiltonian simulation
Approximates the time evolution of a Hamiltonian with non-commuting terms by alternating their individual exponentials.
References
- Efficient quantum algorithms for simulating sparse Hamiltonians
Dominic W. Berry, Graeme Ahokas, Richard Cleve, Barry C. Sanders · 2005
- A Theory of Trotter Error
Andrew M. Childs, Yuan Su, Minh C. Tran, Nathan Wiebe, Shuchen Zhu · 2019
- Simulating Hamiltonian dynamics with a truncated Taylor series
Dominic W. Berry, Andrew M. Childs, Richard Cleve, Robin Kothari, Rolando D. Somma · 2014
Where the routes meet
11 problems nothing else needs — the places a reader arrives. Open a line to see what is recorded inside it, or click its name to go there.
12 lines have something recorded inside that you have not opened.
Of the routes that have been taken apart, 15 are built entirely from named slots, 15 hand off part of the work and finish the rest themselves, and 20 are one undivided act. None of the three is a defect; they are different things to reuse.
Every line on this figure, in words
The lines on this figure
Solve a nonlinear ODE dy/dt = F(y)
- Embed a nonlinear system into a linear one — open · opened: what was inside is drawn in its place
- Koopman linearization
- Carleman linearization, a narrower version of Koopman linearization
- Carleman-Fourier linearization, a narrower version of Koopman linearization
- Koopman-von Neumann lift to phase-space densities
- Level-set exact linearization
- Homotopy perturbation embedding
- Solve a linear ODE du/dt = A(t)u + b(t) — opens into 9 · a way across — click it to open it here
- Choose a time discretization or propagator approximation → Quantum linear solve — open
- Choose a time discretization or propagator approximation — opens into 6 · a way across — click it to open it here
- Quantum linear solve — opens into 5 · a way across — click it to open it here
- Simulate Hamiltonian evolution → Estimate an observable — open
- Simulate Hamiltonian evolution — opens into 3 · a way across — click it to open it here
- Estimate an observable — opens into 4 · a way across — click it to open it here
Estimate an excited-state energy
- Variational quantum deflation — opens into 3 · a way across — click it to open it here
- Subspace-search variational eigensolver — opens into 3 · a way across — click it to open it here
- Quantum subspace expansion
- Quantum equation of motion
- Folded-spectrum variational eigensolver — opens into 3 · a way across — click it to open it here
- Penalty-constrained variational eigensolver — opens into 3 · a way across — click it to open it here
- Multistate contracted variational eigensolver — opens into 3 · a way across — click it to open it here
Every step you can open
1 of these have an object recorded in the middle; the rest open into the methods that fill them.
- Solve a nonlinear ODE dy/dt = F(y)
- Replace a spatial domain with a finite grid
- Discretize a PDE into one linear system
- Embed a nonlinear system into a linear one
- Solve a linear ODE du/dt = A(t)u + b(t)
- Recast a non-Hermitian generator as Hamiltonian evolution
- Choose a time discretization or propagator approximation
- Quantum linear solve
- Matrix function
- QSP phase factors
- Polynomial approximation
- Block-encode a matrix
- Prepare an input state
- Amplify a success branch
- Simulate Hamiltonian evolution
- Estimate an observable
- Compile a circuit to a specific device
- Satisfy the hardware connectivity constraint
- Approximate a continuous rotation in a discrete gate set
- Recover a noiseless expectation value by post-processing
- Build logical qubits at a target logical error rate
- Estimate a Hamiltonian's ground-state energy
- Choose a parameterised trial state
- Minimise the objective over the parameters
- Estimate an excited-state energy
- Measure what the machine can actually do
- Recover the period of a periodic function
- Estimate the eigenphase of a unitary
- Find the item a check accepts
- Walk a graph to the vertex you want
- Search a cost Hamiltonian for the assignment it minimises
What is on this map, counted
What is here, counted
147 nodes — 31 slots and 116 methods.
76 of the 147 link to a record in the Atlas, between them naming 89 records. The rest name papers and nothing else: this graph describes work the catalogue has not got yet, and the nodes with no record are the list of what a corpus pass has to go and read.
0 slots have no method recorded, and 32 methods have not been taken apart. Both are shown as what they are rather than left blank.
Every claim here rests on a source. This graph cites 140 papers; they and the 172 the Atlas cites alone are registered in one place, with what each reports and everywhere it is cited from. Papers