Building Hamiltonians¶
Analog simulations take a Hamiltonian as the operator argument to run(). Most models are built as matrix product operators (MPOs) under the hood; the Hamiltonian wrapper materialises once at construction and can be reused across parameter sweeps.
This page covers the factory methods in the library. For open-system evolution after the Hamiltonian is defined, see Noisy Analog Simulation.
Hamiltonian versus MPO¶
Layer |
Role |
|---|---|
User-facing type passed to |
|
Tensor-network operator; built by factories below |
Typical patterns:
Preset classmethods —
Hamiltonian.ising(...),Hamiltonian.pauli(...), etc.Wrap an MPO —
Hamiltonian.from_mpo(mpo)afterMPO.bose_hubbard(...)or a custom build.Manual data —
Hamiltonian(tensors=...)orHamiltonian(matrix=...)/sparse_matrix=...for small dense/sparse backends (MCWF / Lindblad).
Access the internal MPO with H.mpo when you need bond dimension or tensor cores.
Built-in models (quick reference)¶
Model |
Entry point |
Local dimension per site |
|---|---|---|
Transverse-field Ising |
2 (qubits) |
|
Heisenberg |
2 |
|
Generic Pauli sums |
2 |
|
1D Fermi–Hubbard |
4 (fermionic) or 2 (Jordan–Wigner) |
|
Bose–Hubbard |
|
|
Coupled transmon chain |
alternating qubit / resonator dims |
|
Trapped ion (position grid) |
|
grid points per ion (1–2 ions) |
Open (bc="open") and periodic (bc="periodic") boundaries are supported on the Pauli builders.
Pauli-string Hamiltonians¶
Ising model (shortcut)¶
The transverse-field Ising Hamiltonian on an open chain is
1from mqt.yaqs import Hamiltonian
2
3L = 4
4J, g = 1.0, 0.5
5H_ising = Hamiltonian.ising(L, J, g)
Structured one- and two-body Pauli terms¶
pauli() expands nearest-neighbour two_body and on-site one_body lists into Pauli strings automatically:
1H_ising = Hamiltonian.pauli(
2 length=L,
3 two_body=[(-J, "Z", "Z")],
4 one_body=[(-g, "X")],
5 bc="open",
6)
The Heisenberg model is available as a one-liner as well:
1H_heisenberg = Hamiltonian.heisenberg(L, Jx=1.0, Jy=1.0, Jz=1.0, h=0.2)
Explicit Pauli strings (from_pauli_sum)¶
For arbitrary Pauli strings—including long-range couplings—pass (coefficient, spec) pairs to from_pauli_sum(). Each spec lists operators with site indices, e.g. "Z0 Z3" or "X2":
1from mqt.yaqs import MPO
2
3terms = [(-J, f"Z{i} Z{i+1}") for i in range(L - 1)] + [(-g, f"X{i}") for i in range(L)]
4mpo = MPO()
5mpo.from_pauli_sum(terms=terms, length=L)
6H_custom = Hamiltonian.from_mpo(mpo)
Long-range terms are ordinary entries in terms:
terms.append((0.1, "Z0 Z3")) # Z on sites 0 and 3
Pauli labels are I, X, Y, Z (case-insensitive). Only physical_dimension=2 is supported for this builder.
Fermi–Hubbard (1D)¶
fermi_hubbard_1d() implements
(open boundaries, no chemical potential).
Fermionic sites (default)¶
One physical site has local dimension 4 with basis \(|0\rangle, |\!\downarrow\rangle, |\!\uparrow\rangle, |\!\uparrow\downarrow\rangle\). Ladder operators act on the composite ↑/↓ space per site (not a Jordan–Wigner qubit chain across sites).
1num_sites = 4
2t, u = 1.0, 0.5
3
4H_fermi = Hamiltonian.fermi_hubbard_1d(num_sites, t=t, u=u)
Pair with State using physical_dimensions=[4] * num_sites when building product Fock states (see Initializing Quantum States).
Jordan–Wigner Pauli chain¶
Pass jordan_wigner=True for a qubit chain in the order 1↑, 1↓, 2↑, 2↓, … Here length is the number of spin orbitals (must be even):
1num_orbitals = 2 * num_sites
2H_jw = Hamiltonian.fermi_hubbard_1d(num_orbitals, t=t, u=u, jordan_wigner=True)
Use this mode when you need Pauli-string semantics with full JW signs between orbitals.
Note
The analog MPO factories omit a chemical potential \(\mu\). For a digital Trotter circuit with \(\mu\), see create_1d_fermi_hubbard_circuit() and Noisy Circuit Simulation.
Correctness of the fermionic and JW MPOs is covered by test_fermi_hubbard_1d_* in the package test suite.
Bose–Hubbard¶
The Bose–Hubbard model
is available on bose_hubbard(). Wrap the MPO for analog simulation:
1from mqt.yaqs import Hamiltonian, MPO
2
3local_dim = 3 # occupations 0, 1, …, local_dim - 1
4H_bh = Hamiltonian.from_mpo(
5 MPO.bose_hubbard(
6 length=3,
7 local_dim=local_dim,
8 omega=1.0,
9 hopping_j=0.2,
10 hubbard_u=0.5,
11 )
12)
Initial states must respect the boson dimension, e.g. State(length, initial="zeros", physical_dimensions=[local_dim] * length).
Coupled transmon–resonator chains¶
coupled_transmon() builds an alternating chain of transmon qubits and resonators with local dimensions qubit_dim and resonator_dim:
1H_transmon = Hamiltonian.coupled_transmon(
2 length=3,
3 qubit_dim=3,
4 resonator_dim=5,
5 qubit_freq=5.0,
6 resonator_freq=7.0,
7 anharmonicity=-0.3,
8 coupling=0.1,
9)
A full SWAP-style open-system example is in Transmon-Resonator Chain Emulation.
Trapped-ion position grid¶
trapped_ion() builds a static Hamiltonian for one or two ions on a uniform position grid. Each ion is one MPO site with local dimension equal to the number of grid points. The local terms are a harmonic trap plus a centered finite-difference kinetic energy; for two ions, a softened Coulomb repulsion is compressed into MPO channels (optional SVD truncation via coulomb_cutoff or max_bond_dim).
(the Coulomb term applies only when two masses are supplied).
1from mqt.yaqs import Hamiltonian, MPO
2import numpy as np
3
4positions = np.linspace(-6.0, 6.0, 25)
5H_ion = Hamiltonian.from_mpo(
6 MPO.trapped_ion(
7 positions,
8 masses=[1.0],
9 omega=1.0,
10 trap_center=0.0,
11 )
12)
13
14# Two ions with softened Coulomb repulsion on the same grid spacing
15H_pair = Hamiltonian.from_mpo(
16 MPO.trapped_ion(
17 positions,
18 masses=[1.0, 1.0],
19 omega=1.0,
20 coulomb_strength=1.0,
21 softening_length=float(positions[1] - positions[0]),
22 )
23)
Pair with State using physical_dimensions=[len(positions)] per ion site. A wavepacket reflection benchmark is in Trapped-Ion Position-Grid Emulation.
Note
YAQS applies \(\exp(-\mathrm{i}\,\Delta t\, H)\) during evolution. When using SI units, pass energies and times in consistent units or rescale \(H/\hbar\) explicitly (see the factory docstring).
Manual Hamiltonians¶
For imported MPO cores or small-system dense operators:
# MPO tensor cores (rank-4 per site, already in MPO layout)
H = Hamiltonian(tensors=my_cores)
# Dense matrix (MCWF / Lindblad when state is vector or density_matrix)
H = Hamiltonian(matrix=dense_h, physical_dimension=2)