Fermionic simulations
A fermionic Hamiltonian is described in a similar fashion to bosons and spins - with an Observable
(or many of them) in a Schedule
. The key difference lies within the operators used. The fermionic creation operator \(c^\dagger\) is encoded via the big letter C
, while the annihilation operator \(c\) - through the small letter c
.
Let us look at the following simple Hamiltonian:
Imagine we want to evolve \(H\) for time \(\frac{\pi}{2}\) starting from the state \(\left|01\right>\) (i.e. only site \(1\) is occupied). If at the end we measure the occupation of site \(0\) via the \(n_0 = c^\dagger_0 c_0\) operator, we would expect that the ocupation of the two sites has swapped such that the state of the system is \(\left|10\right>\) and \(\left<n_0\right> = 1\). One way to simulate this behaviour would look like:
import numpy as np
from qat.qpus import QutipQPU
from qat.core import Observable, Term, Schedule
from qat.core.variables import Variable, sin
# Define a time Variable
t = Variable("t", float)
# Create the Schedule
drive = Observable(2, pauli_terms=[Term(1, "Cc", [0, 1]), Term(1, "Cc", [1, 0])])
schedule = Schedule(drive=drive,
tmax=np.pi / 2)
# Construct a job with an observable to measure
job = schedule.to_job(psi_0="01", # start from the 0th site unoccupied and the 1st - occupied
job_type="OBS",
observable=Observable(2, pauli_terms=[Term(1, 'Cc', [0, 0])]))
# Create a QPU and submit the job
qpu = QutipQPU(nsteps=200) # can specify the number of time steps for the integration
res = qpu.submit(job)
print("<n_0 (pi/2)> =", res.value)
<n_0 (pi/2)> = 0.9999999999993716
For a more involved Hamiltonian considering interactions between the fermions in a noisy setting, take a look at the following fermionic notebook.
On Qaptiva 800s there is also the module qat.fermion
specifically dedicated to spin and fermionic computations.
Note
Fermionic simulations are currently only supported for QutipQPU
.