Hamiltonians
Quantum Hamiltonians encode the essential physical properties of a quantum system. For the analog mode of neutral-atom quantum computers, the quantum dynamics is governed by the Rydberg Hamiltonian $\hat{\mathcal{H}}$:
\[i \hbar \dfrac{\partial}{\partial t} | \psi \rangle = \hat{\mathcal{H}}(t) | \psi \rangle, \\ \frac{\mathcal{H}(t)}{\hbar} = \sum_j \frac{\Omega_j(t)}{2} \left( e^{i \phi_j(t) } | g_j \rangle \langle r_j | + e^{-i \phi_j(t) } | r_j \rangle \langle g_j | \right) - \sum_j \Delta_j(t) \hat{n}_j + \sum_{j < k} V_{jk} \hat{n}_j \hat{n}_k,\]
where $\Omega_j$, $\phi_j$, and $\Delta_j$ denote the Rabi frequency, laser phase, and the detuning of the driving laser field on atom (qubit) $j$ coupling the two states $| g_j \rangle$ (ground state) and $| r_j \rangle$ (Rydberg state); $\hat{n}_j = |r_j\rangle \langle r_j|$ is the number operator, and $V_{jk} = C_6/|\mathbf{x}_j - \mathbf{x}_k|^6$ describes the Rydberg interaction (van der Waals interaction) between atoms $j$ and $k$ where $\mathbf{x}_j$ denotes the position of the atom $j$; $C_6$ is the Rydberg interaction constant that depends on the particular Rydberg state used. For Bloqade, the default $C_6 = 862690 \times 2\pi \text{ MHz μm}^6$ for $|r \rangle = \lvert 70S_{1/2} \rangle$ of the $^{87}$Rb atoms; $\hbar$ is the reduced Planck's constant.
One can use the Rydberg Hamiltonian to understand the ground state properties of the corresponding system and to generate interesting quantum dynamics. The Rydberg Hamiltonian is generally specified by atom positions $\mathbf{x}_j$, Rabi frequencies $\Omega_j$, laser phase $\phi_j$, and detunings $\Delta_j$. In Bloqade, we can easily create a Hamiltonian by inputting these variable parameters into the function rydberg_h
. Furthermore, by inputting waveforms for the Rabi frequency and detuning, we can easily generate time-dependent Hamiltonians.
Building Time-Independent Hamiltonians
To specify the Hamiltonian, we first need to specify the atom positions, which determine the Rydberg interactions strengths $V_{jk}$ between pairs of atoms. Here, we generate a square lattice by using the code below:
julia> using Bloqade
julia> atoms = generate_sites(SquareLattice(), 3, 3, scale=6.3)
⠀⠀⠀⠀⠀⠀⠀⠀Approximate Atom Positions⠀⠀⠀⠀⠀⠀⠀⠀ ┌────────────────────────────────────────┐ 20 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ μm │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ 0 │⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⚬⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ └────────────────────────────────────────┘ ⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀20⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀μm⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Please refer to the Lattices page for more details on how to generate lattices and the relevant operations.
Then, the Hamiltonian can be simply built by inputting the generated atom positions atoms
and by specifying the strength of the detuning Δ
, Rabi frequency Ω
, and laser phase ϕ
:
julia> h0 = rydberg_h(atoms; Δ=1.2*2π, Ω=1.1*2π, ϕ=2.1)
nqubits: 9 + ├─ [+] ∑ 2π ⋅ 8.627e5.0/|x_i-x_j|^6 n_i n_j ├─ [+] 2π ⋅ 0.55 ⋅ ∑ e^{2.1 ⋅ im} |0⟩⟨1| + e^{-2.1 ⋅ im} |1⟩⟨0| └─ [-] 2π ⋅ 1.2 ⋅ ∑ n_i
Note that the default value for the Rydberg interaction constant is $C_6 = 2\pi \times 862690 \text{ MHz μm}^6$ to match the default unit used on the hardware. For more information about units, please refer to Bloqade. Instead of using the default value for $C_6$, the users are free to set their own values. For instance, if the users would like to have a chain lattice with nearest-neighbor atoms separated by 1 μm, and interaction strength to be a particular value, say, $2\pi * 10.0^6 \text{ MHz μm}^6$, it can be done with the following code:
julia> atoms = generate_sites(ChainLattice(), 9, scale=1.0)
⠀⠀⠀⠀⠀⠀⠀⠀Approximate Atom Positions⠀⠀⠀⠀⠀⠀⠀⠀ ┌────────────────────────────────────────┐ 1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ μm │⚬⠤⠤⠤⠤⚬⠤⠤⠤⠤⚬⠤⠤⠤⠤⚬⠤⠤⠤⠤⚬⠤⠤⠤⠤⚬⠤⠤⠤⠤⚬⠤⠤⠤⠤⚬⠤⠤⠤⚬│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ -1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ └────────────────────────────────────────┘ ⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀8⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀μm⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
julia> h0 = rydberg_h(atoms; C=2π*10.0^6, Δ=1.2*2π, Ω=1.1*2π, ϕ=2.1)
nqubits: 9 + ├─ [+] ∑ 2π ⋅ 10.0e5.0/|x_i-x_j|^6 n_i n_j ├─ [+] 2π ⋅ 0.55 ⋅ ∑ e^{2.1 ⋅ im} |0⟩⟨1| + e^{-2.1 ⋅ im} |1⟩⟨0| └─ [-] 2π ⋅ 1.2 ⋅ ∑ n_i
Building Time-Dependent Hamiltonians
One can also directly use waveforms (instead of constant values of detuning, Rabi frequency, and laser phase) to build a time-dependent Hamiltonian. First, let us again use the generate_sites
to create a list of atom coordinates:
julia> atoms = generate_sites(ChainLattice(), 5, scale=5.72)
⠀⠀⠀⠀⠀⠀⠀⠀Approximate Atom Positions⠀⠀⠀⠀⠀⠀⠀⠀ ┌────────────────────────────────────────┐ 1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ μm │⚬⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⠤⠤⠤│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ -1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ └────────────────────────────────────────┘ ⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀30⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀μm⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Then, we generate the time-dependent pulses for $\Omega$ and $\Delta$ by using piecewise_linear
. For details on how to create waveforms and the built-in functions, please refer to the page Waveforms.
julia> Ω1 = piecewise_linear(clocks=[0.0, 0.1, 2.1, 2.2], values=2π*[0.0, 6.0, 6.0, 0]);
julia> Δ1 = piecewise_linear(clocks=[0.0, 0.6, 2.1, 2.2], values=2π*[-10.1, -10.1, 10.1, 10.1]);
The time-dependent Hamiltonian can then be easily generated by inputting the waveforms into the function rydberg_h
:
julia> h1 = rydberg_h(atoms; Δ=Δ1, Ω=Ω1)
nqubits: 5 + ├─ [+] ∑ 2π ⋅ 8.627e5.0/|x_i-x_j|^6 n_i n_j ├─ [+] Ω(t) ⋅ ∑ σ^x_i └─ [-] Δ(t) ⋅ ∑ n_i
By specifying the time of h1
, we can access the Hamiltonian at a particular time, e.g.:
julia> ht= h1 |> attime(0.5)
nqubits: 5 + ├─ [+] ∑ 2π ⋅ 8.627e5.0/|x_i-x_j|^6 n_i n_j ├─ [+] 2π ⋅ 3.0 ⋅ ∑ σ^x_i └─ [-] 2π ⋅ -10.1 ⋅ ∑ n_i
Building Hamiltonians with Site-Dependent Waveforms
In certain cases, the user may want to build a Hamiltonian that has site-dependent $\Omega_j$, $\phi_j$, and $\Delta_j$, which may or may not have time dependence.
For the time-independent Hamiltonian, one can for example build a Hamiltonian like:
julia> h0 = rydberg_h(atoms; Δ=1.2*2π*rand(length(atoms)), Ω=1.1*2π*rand(length(atoms)), ϕ=2.1)
nqubits: 5 + ├─ [+] ∑ 2π ⋅ 8.627e5.0/|x_i-x_j|^6 n_i n_j ├─ [+] ∑ Ω_i ⋅ (e^{2.1 ⋅ im} |0⟩⟨1| + e^{-2.1 ⋅ im} |1⟩⟨0|) └─ [-] ∑ Δ_i ⋅ n_i
For time-dependent Hamiltonians, here is an example:
julia> atoms = generate_sites(ChainLattice(), 5, scale=5.72)
⠀⠀⠀⠀⠀⠀⠀⠀Approximate Atom Positions⠀⠀⠀⠀⠀⠀⠀⠀ ┌────────────────────────────────────────┐ 1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ μm │⚬⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⠤⚬⠤⠤⠤⠤⠤⠤⠤⠤⠤│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ -1 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│ └────────────────────────────────────────┘ ⠀0⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀30⠀ ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀μm⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
julia> Δ1 = map(1:length(atoms)) do idx Waveform(t-> idx*sin(2π*t), duration = 2) end
5-element Vector{Waveform{Main.var"#2#4"{Int64}, Int64}}: Waveform(_, 2) Waveform(_, 2) Waveform(_, 2) Waveform(_, 2) Waveform(_, 2)
julia> h =rydberg_h(atoms; Δ=Δ1)
nqubits: 5 + ├─ [+] ∑ 2π ⋅ 8.627e5.0/|x_i-x_j|^6 n_i n_j └─ [-] ∑ Δ_i ⋅ n_i
Hamiltonian Expressions
Bloqade uses "block"s from Yao to build symbolic hamiltonian expressions. This gives users the flexibility to define various kinds of Hamiltonians by simply writing down the expression.
Please refer to the References section below for the types of operators supported by Bloqade.
As an example, we can explicitly add up some Hamiltonian terms to compose a new Hamiltonian, e.g.:
julia> using Bloqade
julia> h = 2π*1.1*SumOfX(5, 1.0) + 2π*1.2*SumOfZ(5, 1.0)
nqubits: 5 + ├─ [scale: 6.911503837897546] ∑ σ^x_i └─ [scale: 7.5398223686155035] ∑ σ^z_i
Convert Hamiltonians to Matrices
An Hamiltonian expression can be converted to a matrix via the mat
interface from Yao:
YaoAPI.mat
— Functionmat([T=ComplexF64], blk)
Returns the most compact matrix form of given block, e.g
Examples
julia> mat(X)
2×2 LuxurySparse.SDPermMatrix{ComplexF64, Int64, Vector{ComplexF64}, Vector{Int64}}:
0.0+0.0im 1.0+0.0im
1.0+0.0im 0.0+0.0im
julia> mat(Float64, X)
2×2 LuxurySparse.SDPermMatrix{Float64, Int64, Vector{Float64}, Vector{Int64}}:
0.0 1.0
1.0 0.0
julia> mat(kron(X, X))
4×4 LuxurySparse.SDPermMatrix{ComplexF64, Int64, Vector{ComplexF64}, Vector{Int64}}:
0.0+0.0im 0.0+0.0im 0.0+0.0im 1.0+0.0im
0.0+0.0im 0.0+0.0im 1.0+0.0im 0.0+0.0im
0.0+0.0im 1.0+0.0im 0.0+0.0im 0.0+0.0im
1.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
julia> mat(kron(X, X) + put(2, 1=>X))
4×4 SparseMatrixCSC{ComplexF64, Int64} with 8 stored entries:
⋅ 1.0+0.0im ⋅ 1.0+0.0im
1.0+0.0im ⋅ 1.0+0.0im ⋅
⋅ 1.0+0.0im ⋅ 1.0+0.0im
1.0+0.0im ⋅ 1.0+0.0im ⋅
This method will return the most compact matrix representation of the operator, e.g.:
julia> mat(X) # will return a PermMatrix
2×2 LuxurySparse.SDPermMatrix{ComplexF64, Int64, Vector{ComplexF64}, Vector{Int64}}: 0.0+0.0im 1.0+0.0im 1.0+0.0im 0.0+0.0im
julia> mat(ht) # will return a SparseMatrixCSC
32×32 SparseMatrixCSC{ComplexF64, Int64} with 191 stored entries: ⎡⢞⣵⠑⢄⠑⢄⠀⠀⠑⢄⠀⠀⠀⠀⠀⠀⎤ ⎢⠑⢄⢟⣵⠀⠀⠑⢄⠀⠀⠑⢄⠀⠀⠀⠀⎥ ⎢⠑⢄⠀⠀⢟⣵⠑⢄⠀⠀⠀⠀⠑⢄⠀⠀⎥ ⎢⠀⠀⠑⢄⠑⢄⢟⣵⠀⠀⠀⠀⠀⠀⠑⢄⎥ ⎢⠑⢄⠀⠀⠀⠀⠀⠀⢟⣵⠑⢄⠑⢄⠀⠀⎥ ⎢⠀⠀⠑⢄⠀⠀⠀⠀⠑⢄⢟⣵⠀⠀⠑⢄⎥ ⎢⠀⠀⠀⠀⠑⢄⠀⠀⠑⢄⠀⠀⢟⣵⠑⢄⎥ ⎣⠀⠀⠀⠀⠀⠀⠑⢄⠀⠀⠑⢄⠑⢄⢟⣵⎦
The Hamiltonian matrix can also be created in a subspace, such as the blockade subspace (see also Working with Subspace). This will allow one to simulate larger system sizes because of the smaller truncated Hilbert space.
For the Rydberg Hamiltonian, we can create a subspace via the blockade_subspace
method, e.g.:
julia> space = blockade_subspace(atoms, 7.5)
5-qubits 13-elements Subspace{Int64, Vector{Int64}}: ───┬─── 1│ 0 2│ 1 3│ 2 ⋮│ ⋮ 11│ 18 12│ 20 13│ 21
The above code means that the blockade subspace only includes states where there is only one Rydberg excitation within the distance of 7.5 μm, which we call the subspace radius $R_s$. If we have a chain of atoms separated by 5.72 μm, the blockade subspace does not contain states with nearest-neighbor atoms being simultaneously excited to the Rydberg state $| r \rangle$.
Once we have defined the space, we can convert the Hamiltonian to a matrix in a subspace basis via the codes below:
julia> h_m = mat(ht, space)
13×13 SparseMatrixCSC{ComplexF64, Int64} with 52 stored entries: ⋅ 18.8496+0.0im 18.8496+0.0im … ⋅ ⋅ 18.8496+0.0im 63.4602+0.0im ⋅ ⋅ ⋅ 18.8496+0.0im ⋅ 63.4602+0.0im ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im 18.8496+0.0im ⋅ ⋅ … ⋅ ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im ⋅ ⋅ 18.8496+0.0im … ⋅ ⋅ ⋅ ⋅ ⋅ 129.338+0.0im 18.8496+0.0im ⋅ ⋅ ⋅ 18.8496+0.0im 195.255+0.0im
We can see that the size of the Hamiltonian matrix in the blockade subspace is much smaller than that in the full Hilbert space.
Diagonalization of the Hamiltonian
Bloqade doesn't provide any built-in diagonalization tool, as there are many existing tools in the Julia ecosystem. Here, we demonstrate how to use the KrylovKit package for this purpose as follows:
julia> using KrylovKit
julia> vals, vecs, info = KrylovKit.eigsolve(h_m, 1, :SR)
([-23.531833672851008, 49.36990716033793, 51.29063792209698, 55.891040715044255, 61.44324863140764, 65.27248354593056, 124.97072996229844, 130.65930913081692, 133.5372339586213, 135.95163912164838, 139.99824815581468, 146.74962587152322, 210.19192698918917], Vector{ComplexF64}[[0.35714347018070086 - 0.7878482865305771im, -0.09238547710851311 + 0.20379972172926805im, -0.08688928863679599 + 0.1916752870652365im, -0.0873092872857905 + 0.19260179207956085im, 0.022897466936713417 - 0.05051115755484169im, -0.08688928863679594 + 0.19167528706523654im, 0.022428975968775522 - 0.04947767987104717im, 0.02142763506876732 - 0.0472687504682352im, -0.09238547710851311 + 0.203799721729268im, 0.02389545835513451 - 0.05271269809701487im, 0.022428975968775466 - 0.0494776798710471im, 0.022897466936713483 - 0.050511157554841646im, -0.0060041806671131265 + 0.013245050926488016im], [-0.04470909825070423 - 0.09637704767599103im, -0.15898580454560465 - 0.34271732296136603im, 0.18318027000144194 + 0.39487205750012994im, -0.16548898563167252 - 0.35673588781954924im, 0.08420702935151325 + 0.18152065686847085im, 0.18318027000143053 + 0.3948720575000986im, -0.005864698279000789 - 0.012642221108356206im, -0.08635560677576265 - 0.18615223202776662im, -0.15898580454558695 - 0.34271732296131746im, 0.08521052338784654 + 0.18368383609520272im, -0.005864698279008519 - 0.012642221108376473im, 0.08420702935150974 + 0.18152065686845845im, -0.032770487773994786 - 0.07064161403680508im], [-3.33663218582414e-16 - 1.5267734992940873e-15im, 0.19802353960671218 + 0.5202801991945043im, -0.12394638330756722 - 0.32565244073899474im, -4.711508960753008e-15 - 1.1957882600777126e-14im, -0.047825235368104325 - 0.12565436934043123im, 0.12394638330758538 + 0.3256524407390299im, -0.08002149719102243 - 0.21024571412608029im, -4.4608414184743594e-15 - 8.28655720430671e-15im, -0.1980235396067252 - 0.5202801991945301im, 2.9178048865929895e-15 + 6.99787450209044e-15im, 0.08002149719102104 + 0.21024571412607712im, 0.04782523536810938 + 0.12565436934044388im, -9.044414522874078e-16 - 2.5478751053409354e-15im], [-0.16455150181692613 + 0.020807613258796896im, -0.4425079064452682 + 0.05595532875484238im, -0.1261452287095603 + 0.01595112232005556im, 0.6493926703259865 - 0.08211600251613052im, -0.04810764219429005 + 0.006083233531856234im, -0.1261452287095585 + 0.015951122320056705im, 0.1504578799250478 - 0.019025468273762423im, 0.06474785220408702 - 0.008187395758316549im, -0.4425079064452676 + 0.05595532875484337im, 0.23989246681615412 - 0.03033451301320143im, 0.15045787992504817 - 0.019025468273762763im, -0.04810764219429006 + 0.0060832335318556im, -0.01943300075047681 + 0.002457311903016425im], [1.2305694657710475e-15 + 1.8431436932253575e-16im, -0.2404510904151611 - 0.2814374040486514im, -0.3834280957067683 - 0.44878568738745434im, -3.7470027081099033e-16 + 1.3877787807814457e-17im, 0.06675575100666656 + 0.0781346644600194im, 0.38342809570677083 + 0.44878568738745545im, -0.041027222986983185 - 0.04802055633370422im, -1.0477729794899915e-15 - 4.145989107584569e-16im, 0.24045109041516313 + 0.2814374040486508im, -4.85722573273506e-16 + 2.914335439641036e-16im, 0.04102722298698217 + 0.048020556333703925im, -0.06675575100666693 - 0.07813466446001917im, 9.627715291671279e-17 - 1.3357370765021415e-16im], [-0.2922444728761504 - 0.32757252874336196im, -0.06346463070958049 - 0.07113657056606772im, -0.27585755030338194 - 0.3092046683946133im, -0.3333435397898779 - 0.3736398680002244im, 0.13009738999244025 + 0.1458242498252354im, -0.27585755030338016 - 0.3092046683946082im, 0.10339568189229068 + 0.11589469817947413im, 0.1623261537834164 + 0.18194899685426033im, -0.06346463070958182 - 0.07113657056606944im, 0.05264952205601112 + 0.059014074440080375im, 0.10339568189229108 + 0.11589469817947635im, 0.130097389992441 + 0.14582424982523579im, -0.04536761532076489 - 0.05085189234691555im], [0.021160634111007832 - 0.025305880763786093im, 0.057871297487183636 - 0.0692079521896008im, -0.023451511527067363 + 0.028045527904373445im, 0.0714533825835903 - 0.08545068972620834im, 0.10600432498345219 - 0.12676996324422832im, -0.02345151152706502 + 0.028045527904373684im, -0.30010477015245934 + 0.35889357049895615im, 0.20241630830826024 - 0.24206850020764573im, 0.05787129748718405 - 0.0692079521896018im, 0.3617875396866764 - 0.43265964021238523im, -0.3001047701524664 + 0.35889357049895787im, 0.10600432498346155 - 0.12676996324423123im, -0.15388753935860155 + 0.18403322422249357im], [-7.628446485608009e-16 + 4.3021142204224816e-16im, -0.037583495376516854 + 0.01051296826563418im, -0.11286391599053325 + 0.03157063373848118im, -5.2111093218343285e-15 + 2.3765711620882257e-15im, -0.5363487781523549 + 0.1500290919601718im, 0.11286391599053607 - 0.03157063373848011im, 0.4023626786859452 - 0.11255009758737744im, 4.371503159461554e-15 + 6.7133798520302435e-15im, 0.03758349537651421 - 0.010512968265634633im, 2.192690473634684e-15 - 2.2967738821932926e-15im, -0.40236267868594 + 0.11255009758737035im, 0.5363487781523371 - 0.15002909196016423im, 4.666406150377611e-15 - 1.502270530195915e-15im], [0.027374207130190925 - 0.013566345447056673im, -0.0388971089977867 + 0.019276964444895704im, 0.01061732608550408 - 0.0052618259486034435im, 0.25048858554215936 - 0.12413929162761908im, 0.45193405752743165 - 0.2239733744450769im, 0.010617326085507089 - 0.005261825948604422im, -0.08323101262386767 + 0.041248342419334214im, 0.09532887715659656 - 0.047243906369092765im, -0.03889710899778556 + 0.019276964444896252im, -0.5406851751093075 + 0.2679574180450245im, -0.08323101262387841 + 0.0412483424193378im, 0.4519340575274463 - 0.2239733744450783im, -0.1109224788379834 + 0.05497191785694515im], [-0.03885851930640877 - 0.019733636492009474im, -0.18654421997125917 - 0.09473330153346939im, 0.10960738351301579 + 0.05566224091120565im, -0.12639178349725638 - 0.06418591226919065im, -0.22360898236732127 - 0.11355600916212658im, 0.1096073835130142 + 0.05566224091120748im, -0.16444317273621598 - 0.08350966151800443im, 0.6248288683254262 + 0.31730868744692425im, -0.18654421997125928 - 0.0947333015334707im, -0.29049955632533886 - 0.14752524666239994im, -0.16444317273620912 - 0.08350966151801109im, -0.2236089823673295 - 0.11355600916212824im, 0.2344850972132509 + 0.11907925864886545im], [4.185020385794047e-17 - 1.6089560239684886e-16im, -0.018251715188798128 + 0.2263079452305019im, 0.010303308386539336 - 0.12775350294011514im, 5.585809592645319e-16 + 7.979727989493313e-17im, -0.03227427589489441 + 0.400177462009608im, -0.010303308386540715 + 0.12775350294011387im, -0.04183628565701084 + 0.5187394031288454im, -2.5673907444456745e-15 - 1.6046192152785466e-15im, 0.018251715188799006 - 0.2263079452305016im, -6.800116025829084e-16 + 4.2327252813834093e-16im, 0.04183628565701047 - 0.5187394031288457im, 0.03227427589489709 - 0.4001774620096082im, -6.583275591331983e-16 + 1.5612511283791264e-17im], [0.09284447605945473 + 0.08578130559678351im, 0.14888984715658551 + 0.13756300882153533im, 0.1825167462201289 + 0.1686317317792124im, 0.0600097902268342 + 0.05544452801855905im, 0.0861586752712463 + 0.07960412904397089im, 0.1825167462201283 + 0.16863173177921312im, 0.3184416407667695 + 0.2942161005234503im, 0.39519018696082253 + 0.36512597879089875im, 0.14888984715658554 + 0.13756300882153435im, 0.16044625676793614 + 0.148240261217662im, 0.31844164076677145 + 0.29421610052344804im, 0.08615867527124398 + 0.07960412904397007im, -0.12931567205230166 - 0.11947794476936285im], [0.015901138455056113 + 0.009116142636757292im, 0.05674419842029936 + 0.032531520184542834im, 0.004058396462885201 + 0.0023266837866192385im, 0.05570885132311302 + 0.031937954394069205im, 0.2088783465103543 + 0.11975021825640385im, 0.004058396462885225 + 0.0023266837866192706im, 0.01379859940546595 + 0.007910754360339245im, 0.0018922868817565605 + 0.001084850444671873im, 0.056744198420299374 + 0.03253152018454277im, 0.20313926307635383 + 0.11645999451950148im, 0.013798599405465933 + 0.007910754360339318im, 0.2088783465103544 + 0.11975021825640382im, 0.7835116697964305 + 0.44918822382534934im]], ConvergenceInfo: 13 converged values after 1 iterations and 13 applications of the linear map; norms of residuals are given by (6.631142327088176e-38, 1.3241569758589809e-31, 2.9670960553737117e-31, 9.945612560095271e-32, 1.4484486935862632e-30, 2.83373152047111e-32, 4.047897400477171e-31, 2.369482969037308e-30, 8.682753461551038e-30, 2.4831345667310115e-30, 1.4090511307531003e-30, 8.457204200332192e-33, 1.405053756899771e-37). )
where the vals
and vecs
store the calculated eigenvalues and eigenvectors respectively.
Low-Level Representation of the Hamiltonian
Besides the symbolic representation, in order to achieve the best possible performance, we use a lower-level representation of the Hamiltonian in Bloqade, which is the Hamiltonian
and StepHamiltonian
type:
BloqadeExpr.Lowlevel.Hamiltonian
— Typestruct Hamiltonian
Hamiltonian
stores the dynamic prefactors of each term. The actual hamiltonian is the sum of f_i(t) * t_i
where f_i
and t_i
are entries of fs
and ts
.
Missing docstring for BloqadeExpr.StepHamiltonian
. Check Documenter's build log for details.
The Hamiltonian
type represents the following Hamiltonian expression
\[f_1(t) H_1 + f_2(t) H_2 + \cdots + f_n(t) H_n + H_c,\]
where $f_i(t)$ are time-dependent parameters of the Hamiltonian, $H_i$ are time-independent local terms of the Hamiltonian as linear operators (in Julia, this means objects that support LinearAlgebra.mul!
interface), and $H_c$ is the constant component of the Hamiltonian.
A Hamiltonian
object supports callable methods, which will produce a StepHamiltonian
that is time-independent, e.g.:
julia> using BloqadeExpr
julia> h = BloqadeExpr.Hamiltonian(Float64, SumOfX(5, sin) + SumOfZ(5, cos))
Hamiltonian number of dynamic terms: 2 storage size: 48 bytes
julia> h(0.1)
BloqadeExpr.Lowlevel.SumOfLinop{LinearAlgebra.Hermitian, Vector{Float64}, Tuple{SparseMatrixCSC{Float64, Int64}, Diagonal{Float64, Vector{Float64}}}}([0.09983341664682815, 0.9950041652780258, 1.0], (sparse([2, 3, 5, 9, 17, 1, 4, 6, 10, 18 … 15, 23, 27, 29, 32, 16, 24, 28, 30, 31], [1, 1, 1, 1, 1, 2, 2, 2, 2, 2 … 31, 31, 31, 31, 31, 32, 32, 32, 32, 32], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 … 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 32, 32), [5.0 0.0 … 0.0 0.0; 0.0 3.0 … 0.0 0.0; … ; 0.0 0.0 … -3.0 0.0; 0.0 0.0 … 0.0 -5.0]))
Here, we see that the Hamiltonian expression written as Yao blocks are automatically analyzed into time-dependent terms and constant terms. A more complicated example can be SumOfXPhase
:
julia> using BloqadeExpr
julia> h = BloqadeExpr.Hamiltonian(Float64, SumOfXPhase(5, sin, cos) + SumOfZ(5, cos))
Hamiltonian number of dynamic terms: 3 storage size: 88 bytes
julia> h(0.1)
BloqadeExpr.Lowlevel.SumOfLinop{LinearAlgebra.Hermitian, Vector{Number}, Tuple{SparseMatrixCSC{Float64, Int64}, SparseMatrixCSC{Float64, Int64}, Diagonal{Float64, Vector{Float64}}}}(Number[0.0543592350476218 + 0.08373639975791049im, 0.0543592350476218 - 0.08373639975791049im, 0.9950041652780258, 1.0], (sparse([1, 1, 2, 3, 1, 2, 5, 3, 5, 4 … 29, 15, 23, 27, 29, 16, 24, 28, 30, 31], [2, 3, 4, 4, 5, 6, 6, 7, 7, 8 … 30, 31, 31, 31, 31, 32, 32, 32, 32, 32], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 … 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 32, 32), sparse([2, 3, 5, 9, 17, 4, 6, 10, 18, 4 … 29, 28, 30, 28, 31, 32, 30, 31, 32, 32], [1, 1, 1, 1, 1, 2, 2, 2, 2, 3 … 25, 26, 26, 27, 27, 28, 29, 29, 30, 31], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 … 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 32, 32), [5.0 0.0 … 0.0 0.0; 0.0 3.0 … 0.0 0.0; … ; 0.0 0.0 … -3.0 0.0; 0.0 0.0 … 0.0 -5.0]))
References
BloqadeExpr.rydberg_h
— Functionrydberg_h(atoms; [C=2π * 862690 * MHz*µm^6], Ω[, ϕ, Δ])
Create a rydberg hamiltonian
\[∑ \frac{C}{|x_i - x_j|^6} n_i n_j + \frac{Ω}{2} σ_x - Δ σ_n\]
shorthand for
RydInteract(C, atoms) + SumOfXPhase(length(atoms), Ω, ϕ) - SumOfN(length(atoms), Δ)
Arguments
atoms
: a collection of atom positions.
Keyword Arguments
C
: optional, default unit isMHz*µm^6
, interation parameter, see alsoRydInteract
.Ω
: optional, default unit isMHz
, Rabi frequencies, divided by 2, see alsoSumOfX
.Δ
: optional, default unit isMHz
, detuning parameter, seeSumOfN
.ϕ
: optional, does not have unit, the phase, seeSumOfXPhase
.
The rabi frequencies are divided by two in the Rydberg hamiltonian unlike directly constructing via SumOfX
or SumOfXPhase
.
The parameters of Hamiltonian have their own default units to match hardware, one can use Unitful.jl
to specify their units explicitly. If the units are specified explicitly, they will be converted to default units automatically.
Example
julia> using Bloqade
julia> atoms = [(1, ), (2, ), (3, ), (4, )]
4-element Vector{Tuple{Int64}}:
(1,)
(2,)
(3,)
(4,)
julia> rydberg_h(atoms)
∑ 5.42e6/|x_i-x_j|^6 n_i n_j
julia> rydberg_h(atoms; Ω=0.1)
nqubits: 4
+
├─ ∑ 5.42e6/|x_i-x_j|^6 n_i n_j
└─ 0.05 ⋅ ∑ σ^x_i
Except the standard operators from Yao, the following operators are also supported by Bloqade:
BloqadeExpr.RydInteract
— Typestruct RydInteract{D} <: AbstractTerm{D}
RydInteract(;atoms, C=2π * 862690MHz⋅μm^6)
Type for Rydberg interactive term.
Expression
\[\sum_{i, j} \frac{C}{|x_i - x_j|^6} n_i n_j\]
Keyword Arguments
atoms
: a list of atom positions, must be typeRydAtom
, default unit isμm
.C
: the interaction strength, default unit isMHz⋅μm^6
. default value is2π * 862690 * MHz*µm^6
.
BloqadeExpr.SumOfX
— Typestruct SumOfX <: AbstractTerm{2}
SumOfX(nsites, Ω)
Term for sum of X operators.
The following two expressions are equivalent
julia> SumOfX(nsites=5)
∑ σ^x_i
julia> sum([X for _ in 1:5])
nqudits: 1
+
├─ X
├─ X
├─ X
├─ X
└─ X
Expression
\[\sum_i Ω σ^x_i\]
BloqadeExpr.SumOfXPhase
— Typestruct SumOfXPhase <: AbstractTerm{2}
SumOfXPhase(;nsites, Ω=1, ϕ)
Sum of XPhase
operators.
The following two expressions are equivalent
julia> SumOfXPhase(nsites=5, ϕ=0.1)
1.0 ⋅ ∑ e^{0.1 ⋅ im} |0⟩⟨1| + e^{-0.1 ⋅ im} |1⟩⟨0|
julia> sum([XPhase(0.1) for _ in 1:5])
nqudits: 1
+
├─ XPhase(0.1)
├─ XPhase(0.1)
├─ XPhase(0.1)
├─ XPhase(0.1)
└─ XPhase(0.1)
But may provide extra speed up.
Expression
\[\sum_i Ω ⋅ (e^{ϕ ⋅ i} |0⟩⟨1| + e^{-ϕ ⋅ i} |1⟩⟨0|)\]
BloqadeExpr.SumOfZ
— Typestruct SumOfZ <: AbstractTerm{2}
SumOfZ(;nsites, Δ=1)
Sum of Pauli Z operators.
The following two expression are equivalent
julia> SumOfZ(nsites=5)
∑ σ^z_i
julia> sum([Z for _ in 1:5])
nqudits: 1
+
├─ Z
├─ Z
├─ Z
├─ Z
└─ Z
Expression
\[\sum_i Δ ⋅ σ^z_i\]
BloqadeExpr.SumOfN
— Typestruct SumOfN <: AbstractTerm{2}
SumOfN(;nsites[, Δ=1])
Sum of N operators.
The following two expression are equivalent
julia> SumOfN(nsites=5)
∑ n_i
julia> sum([Op.n for _ in 1:5])
nqudits: 1
+
├─ P1
├─ P1
├─ P1
├─ P1
└─ P1
But may provide extra speed up.
Expression
\[\sum_i Δ ⋅ n_i\]
BloqadeExpr.XPhase
— TypeXPhase{T} <: PrimitiveBlock{2}
XPhase operator for 2-level Rydberg system.
\[e^{ϕ ⋅ i} |0⟩⟨1| + e^{-ϕ ⋅ i} |1⟩⟨0|\]