Quantum trajectories

Claim: you should not use master equation solvers. You don't pay the exponential cost when working with classical probability distributions, instead we use Monte Carlo simulations. How can we do the same with quantum systems?

Good resources

QuantumOptics documentation

QuTiP documentation

Mølmer, Castin, and Dalibard

Monte Carlo wavefunction in QuantumOptics.jl

using QuantumOptics

cutoff = 32
B = FockBasis(cutoff)
a = destroy(B)
ω = 1.0
H = ω*a'*a

γ = 0.1
L = [√γ*a]

ψ = fockstate(B, 18)

ts = 0:0.01:3*2*π

_, ρs = timeevolution.master(ts,ψ,H,L)

_, ψs = timeevolution.mcwf(ts,ψ,H,L)
using CairoMakie
fig = Figure()
ax = Axis(fig[1,1], aspect = DataAspect())

lines!(ax,ts,real.(expect.((a'*a,),ρs)))
lines!(ax,ts,real.(expect.((a'*a,),ψs)))

fig
Example block output

Is the environment photon counting or doing homodyne readout?

We can make lots of trajectories and average them...

fig = Figure()
ax = Axis(fig[1,1], aspect = DataAspect())

_, ρs = timeevolution.master(ts,ψ,H,L)

lines!(ax,ts,real.(expect.((a'*a,),ρs)))

trajectories = []
n_traj = 100

for _ in 1:n_traj
    _, ψs = timeevolution.mcwf(ts,ψ,H,L)
    push!(trajectories,ψs)
    lines!(ax,ts,real.(expect.((a'*a,),ψs)), color = (:gray,0.1))
end

sols_avg = sum([dm.(ψs) for ψs in trajectories])/n_traj
lines!(ax,ts, real.(expect.((a'*a,), sols_avg)))

fig
Example block output

Cat states

α = 4.0

l0 = (coherentstate(B,α) + coherentstate(B,-α)) / √2
l1 = (coherentstate(B,1im*α) + coherentstate(B,-1im*α)) / √2

mix0 = (dm(coherentstate(B,α)) + dm(coherentstate(B,-α))) / 2
mix1 = (dm(coherentstate(B,1im*α)) + dm(coherentstate(B,-1im*α))) / 2
#TODO: make 4 panel Wigner function plot
H = ω*a'*a
ts = 0:0.01:π/2

_, ψs = timeevolution.schroedinger(ts,l0,H)

lines(ts, real.(expect.((projector(l0),), ψs)))
lines!(ts, real.(expect.((projector(l1),), ψs)))
current_figure()
Example block output

We can think of this as a logical gate, it exchanges our two states.

We can add loss:

γ = 0.01
L = [√γ*a]
_,ρs = timeevolution.master(ts,l0,H,L);
lines!(ts, real.(expect.((projector(l0),),ρs)), linestyle=:dash)
lines!(ts, real.(expect.((projector(l1),),ρs)), linestyle=:dash)
current_figure()
Example block output

We can use non Hermitian time evolution as a worst case analysis.

Hnotherm = H - im/1 *L[1]'*L[1]
_,ψnhs = timeevolution.schroedinger(ts,l0,Hnotherm);
lines!(ts, real.(expect.((projector(l0),),ψnhs)), linestyle=:dot)
lines!(ts, real.(expect.((projector(l1),),ψnhs)), linestyle=:dot)
current_figure()
Example block output