Spin fermion transforms¶
Chemistry problems involve electrons, which are fermions, while quantum computers work in the language of qubits (or, equivalently, spins or two-level systems).
The qat.fermion
module of QLM comes with a few tools to go from the fermionic representation to the spin representation. In particular, three transformations are implemented:
- Jordan-Wigner transformation,
- parity transformation,
- Bravyi-Kitaev transformation.
Fermionic hamiltonian to spin Hamiltonian¶
Let us look at a simple example with a single $c^\dagger_0 c_1 + \frac{1}{2}c^\dagger_0 c^\dagger_1 c_0 c_1$ operator acting on 3 qubits.
import numpy as np
from qat.core import Term
from qat.fermion.hamiltonians import FermionHamiltonian
# We define an arbitrary fermionic Hamiltonian H_f
nqbits = 3
H_fermion = FermionHamiltonian(nqbits, [Term(1.0, "Cc", [0, 1]), Term(0.5, "CCcc", [0, 1, 0, 1])])
print(f"H_fermion = {H_fermion}")
H_fermion = 1.0 * (Cc|[0, 1]) + 0.5 * (CCcc|[0, 1, 0, 1])
We can convert the fermionic Hamiltonian
operator to a spin Hamiltonian
operator using the method .to_spin
. By default the Jordan-Wigner transform is used.
# Using the Jordan-Wigner transform
H_spin = H_fermion.to_spin("jordan-wigner")
# Using the Bravyi-Kitaev transform
H_spin = H_fermion.to_spin("bravyi-kitaev")
# Using the parity transform
H_spin = H_fermion.to_spin("parity")
print(f"H_spin = {H_spin}")
H_spin = (-0.125+0j) * I^3 + -0.25j * (Y|[0]) + (-0.25+0j) * (XZ|[0, 1]) + (0.25+0j) * (X|[0]) + 0.25j * (YZ|[0, 1]) + (-0.125+0j) * (Z|[1]) + (0.125+0j) * (Z|[0]) + (0.125+0j) * (ZZ|[0, 1])
Otherwise, one can directly use the transformation functions.
from qat.fermion.transforms import transform_to_jw_basis, transform_to_parity_basis, transform_to_bk_basis
# Using the Jordan-Wigner transform
H_spin = transform_to_jw_basis(H_fermion)
# Using the Bravyi-Kitaev transform
H_spin = transform_to_bk_basis(H_fermion)
# Using the parity transform
H_spin = transform_to_parity_basis(H_fermion)
print(f"H_spin = {H_spin}")
H_spin = (-0.125+0j) * I^3 + -0.25j * (Y|[0]) + (-0.25+0j) * (XZ|[0, 1]) + (0.25+0j) * (X|[0]) + 0.25j * (YZ|[0, 1]) + (-0.125+0j) * (Z|[1]) + (0.125+0j) * (Z|[0]) + (0.125+0j) * (ZZ|[0, 1])
Electronic-structure Hamiltonian to spin Hamiltonian¶
You can also transform Hamiltonians of the ElectronicStructureHamiltonian
type.
from qat.fermion.hamiltonians import ElectronicStructureHamiltonian
hpq = np.array(
[
[0.0, 1.0, 0.0, 0.0],
[1.0, 0.0, 1.0, 0.0],
[0.0, 1.0, 0.0, 1.0],
[0.0, 0.0, 1.0, 0.0],
]
)
hpqrs = np.zeros((4, 4, 4, 4))
hpqrs[0, 1, 1, 0] = 0.6
hpqrs[1, 0, 0, 1] = 0.6
hpqrs[2, 0, 0, 2] = 0.6
# We define the fermionic operator H_f, an `ElectronicStructureHamiltonian` object.
H_elec = ElectronicStructureHamiltonian(hpq, hpqrs)
Just like before we convert the fermionic operator $H_f$ to a spin Hamiltonian operator using the method .to_spin
.
# Using the Jordan-Wigner transform
H_spin = H_elec.to_spin("jordan-wigner")
# # Using the Bravyi-Kitaev transform
H_spin = H_elec.to_spin("bravyi-kitaev")
# # Using the parity transform
H_spin = H_elec.to_spin("parity")
print(f"H_spin = {H_spin}")
H_spin = (0.22499999999999998+0j) * I^4 + (0.5+0j) * (X|[0]) + (-0.5+0j) * (XZ|[0, 1]) + (0.5+0j) * (X|[1]) + (-0.5+0j) * (ZXZ|[0, 1, 2]) + (0.5+0j) * (X|[2]) + (-0.5+0j) * (ZXZ|[1, 2, 3]) + (0.15+0j) * (Z|[1]) + (-0.15+0j) * (ZZ|[0, 1]) + (0.075+0j) * (ZZZ|[0, 1, 2]) + (-0.22499999999999998+0j) * (Z|[0]) + (-0.075+0j) * (ZZ|[1, 2])
Or, using the transformation functions directly:
from qat.fermion.transforms import transform_to_jw_basis, transform_to_parity_basis, transform_to_bk_basis
# Using the Jordan-Wigner transform
H_spin = transform_to_jw_basis(H_elec)
# Using the Bravyi-Kitaev transform
H_spin = transform_to_bk_basis(H_elec)
# Using the parity transform
H_spin = transform_to_parity_basis(H_elec)
print(f"H_spin = {H_spin}")
H_spin = (0.22499999999999998+0j) * I^4 + (0.5+0j) * (X|[0]) + (-0.5+0j) * (XZ|[0, 1]) + (0.5+0j) * (X|[1]) + (-0.5+0j) * (ZXZ|[0, 1, 2]) + (0.5+0j) * (X|[2]) + (-0.5+0j) * (ZXZ|[1, 2, 3]) + (0.15+0j) * (Z|[1]) + (-0.15+0j) * (ZZ|[0, 1]) + (0.075+0j) * (ZZZ|[0, 1, 2]) + (-0.22499999999999998+0j) * (Z|[0]) + (-0.075+0j) * (ZZ|[1, 2])
Note : Some fermionic Hamiltonian can be casted into an electronic-structure Hamiltonian form.¶
?H_fermion.to_electronic
H = H_fermion.to_electronic()