Time evolution builder
The TimeEvolutionBuilder algorithm in QDK/Chemistry constructs quantum circuits that implement the Hamiltonian simulation unitary \(U(t) = e^{-iHt}\).
Following QDK/Chemistry’s algorithm design principles, it takes a QubitHamiltonian and a time parameter as input and produces a TimeEvolutionUnitary as output.
Overview
Hamiltonian simulation — constructing the unitary \(U(t) = e^{-iHt}\) — is a central subroutine in many quantum algorithms.
The TimeEvolutionBuilder provides a unified interface for methods that construct this operator from a QubitHamiltonian.
QDK/Chemistry currently provides Trotter-Suzuki product formulas for this task.
These decompose \(e^{-iHt}\) into a sequence of elementary Pauli rotations \(e^{-i\theta P}\) that can be directly implemented as quantum gates, with controllable approximation error via the Trotter order and number of time divisions [Suz92].
The resulting TimeEvolutionUnitary objects wrap a PauliProductFormulaContainer — a list of exponentiated Pauli terms with a repetition count.
Using the TimeEvolutionBuilder
Note
This algorithm is currently available only in the Python API.
This section demonstrates how to create, configure, and run a time evolution builder.
The run method returns a TimeEvolutionUnitary object that can be used by any algorithm that requires a Hamiltonian simulation unitary (e.g., PhaseEstimation).
Input requirements
The TimeEvolutionBuilder requires the following inputs:
- QubitHamiltonian
A
QubitHamiltoniancontaining the Pauli-string representation of the Hamiltonian. This can be obtained from the QubitMapper algorithm, constructed from a model Hamiltonian, or built directly.- Time
A float specifying the evolution time \(t\) in \(U(t) = e^{-iHt}\).
Creating a builder
from qdk_chemistry.algorithms import create
# Create a time evolution builder
trotter = create("time_evolution_builder", "trotter")
Configuring settings
Settings vary by implementation. See Available implementations below for implementation-specific options.
# Configure a second-order Trotter builder with automatic step count
trotter = create("time_evolution_builder", "trotter")
trotter.settings().set("order", 2)
trotter.settings().set("target_accuracy", 1e-3)
trotter.settings().set("error_bound", "commutator")
Running the builder
import numpy as np
from qdk_chemistry.algorithms import create
from qdk_chemistry.data import Structure
# 1. Setup molecule
coords = np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 1.4]])
symbols = ["H", "H"]
structure = Structure(coords, symbols=symbols)
# 2. SCF
scf_solver = create("scf_solver")
E_scf, wfn_scf = scf_solver.run(
structure, charge=0, spin_multiplicity=1, basis_or_guess="sto-3g"
)
# 3. Hamiltonian construction
hamiltonian_constructor = create("hamiltonian_constructor")
hamiltonian = hamiltonian_constructor.run(wfn_scf.get_orbitals())
# 4. Qubit mapping
qubit_mapper = create("qubit_mapper", encoding="jordan-wigner")
qubit_ham = qubit_mapper.run(hamiltonian)
# 5. Build time evolution unitary
trotter = create("time_evolution_builder", "trotter", order=2)
evolution = trotter.run(qubit_ham, time=0.1)
print(f"Container type: {evolution.get_container_type()}")
print(f"Number of qubits: {evolution.get_num_qubits()}")
print(evolution.get_summary())
Available implementations
QDK/Chemistry’s TimeEvolutionBuilder provides a unified interface for Hamiltonian simulation methods.
You can discover available implementations programmatically:
from qdk_chemistry.algorithms import registry
# List all registered time evolution builder implementations
implementations = registry.available("time_evolution_builder")
print(implementations) # e.g. ['trotter', 'qdrift', 'partially_randomized']
Trotter-Suzuki product formulas
Factory name: "trotter"
The Trotter-Suzuki decomposition approximates the time-evolution operator as a product of individual Pauli exponentials. For a Hamiltonian \(H = \sum_j \alpha_j P_j\):
First-order Trotter (\(p = 1\)):
Second-order Trotter (Strang splitting, \(p = 2\)):
Higher even orders are constructed via the recursive Suzuki composition [Suz92]:
where \(u_k = 1/(4 - 4^{1/(2k-1)})\).
The number of Trotter steps \(N\) can be specified directly (num_divisions) or computed automatically from a target_accuracy using one of two error bounds:
- Commutator bound (default)
A tighter bound [CST+21] based on nested commutators: \(N = \lceil \frac{t^{2}}{2\epsilon} \sum_{j<k}\lVert[\alpha_jP_j,\alpha_kP_k]\rVert \rceil\)
- Naive bound
A looser triangle-inequality bound: \(N = \lceil (\sum_j|\alpha_j|)^{2}t^{2}/\epsilon \rceil\)
When both num_divisions and target_accuracy are specified, the builder uses whichever requires more Trotter steps.
Settings
Setting |
Type |
Description |
|---|---|---|
|
int |
Trotter-Suzuki order (1 for first-order, 2+ for higher even orders). Default is 1. |
|
float |
Target approximation error \(\epsilon\). When set to 0.0 (default), automatic step-count estimation is disabled. |
|
int |
Explicit number of Trotter steps \(N\). When set to 0 (default), determined from |
|
str |
Error bound strategy: |
|
float |
Coefficient threshold below which Pauli terms are discarded. Default is 1e-12. |
Further reading
The above examples can be downloaded as a complete Python script.
PhaseEstimation: Quantum phase estimation algorithms
QubitMapper: Map fermionic Hamiltonians to qubit operators
Settings: Configuration settings for algorithms
Factory Pattern: Understanding algorithm creation