Hamiltonians
The Hamiltonian is the foundation of all quantum system modelling in QruiseML. It encodes the physics of your system — the energy levels of qubits, their interactions, and the effects of external drives.
Everything else in QruiseML builds on the Hamiltonian: the time-evolution equations you solve, the drives you design, the problems you define, and the optimisation you run. A well-defined Hamiltonian is therefore essential for accurate simulation and effective control.
This page walks you through how to define your system Hamiltonian in QruiseML.
In QruiseML, the Hamiltonian, \(H\), is defined as the sum of a stationary (time-independent) term and a time-dependent term:
\(H_0\) defines the stationary part, which specifies the intrinsic energy levels of the system. The sum term defines the time-dependent part, where \(H_k\) are Hermitian operators describing the coupling of the system to the \(k^\text{th}\) drive channel, and \(f_k(t; \{p\}_k)\) are the corresponding drive functions, whose parameters \(\{p\}_k\) collectively form the complete parameter set \(p\).
Defining the Hamiltonian¶
In QruiseML, you specify your Hamiltonian with the Hamiltonian() class:
H0is a single time-independent operator, so you can scale it directly with a constant, i.e.prefactor * operator.Htmust be provided as(drive, operator)pairs, for example[(drive1, operator1), (drive2, operator2), ...].
For example, let's assume the following Hamiltonian:
where \(\omega\) is your qubit resonance frequency, \(\sigma_{x,z}\) are the Pauli-X and -Z operators and \(c_x(t)\) is your time-dependent drive term in the \(x\) direction.
Assuming you've already defined your drive as drive_x, your code would look like this:
import qutip as qt
from qruise.toolset import Hamiltonian
omega = 2.0 # qubit frequency
H = qr.Hamiltonian(omega / 2 * qt.sigmaz(), [(drive_x, qt.sigmax())])
You can see that QruiseML uses QuTiP operators, so you can reuse what you already know. Alternatively, you can pass your own operators as NumPy arrays.
If there's no stationary term in your Hamiltonian, you can simply pass None:
Tip
You can learn how to define your drives here.
Operators¶
Hamiltonians are built from quantum operators. In QruiseML, we typically use QuTiP operators.
Ladder operators¶
The ladder operators, also known as the creation and annihilation operators, raise or lower the excitation number of a quantum state, respectively. They are fundamental in describing oscillators, multi-level systems, and qubits.
They act on Fock states \(|n\rangle\), which are number states with exactly \(n\) excitations (\(n=0,1,2,...\)) with the annihilation, \(a\), and creation, \(a^\dagger\), operators given by
and
For an \(N\)-level system, you can define the annihilation and creation operators like so:
Pauli operators¶
The Pauli operators are the special case of ladder operators for two-level systems, i.e. \(N=2\). They're denoted as \(\sigma_x\), \(\sigma_y\), and \(\sigma_z\), corresponding to rotations around the \(x\)-, \(y\)-, and \(z\)-axis of the Bloch sphere, respectively:
# Pauli operators
X = qt.sigmax()
Y = qt.sigmay()
Z = qt.sigmaz()
# Two-qubit coupling
XX = qt.tensor(qt.sigmax(), qt.sigmax())
Custom operators¶
You can also define custom operators using NumPy arrays or QuTiP objects: