Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add GroundStateProjection operator for FockSpace #229

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ Destroy
Create
```

```@docs
GroundStateProjection
```

```@docs
Transition
```
Expand Down Expand Up @@ -330,4 +334,4 @@ MeanfieldNoiseEquations

```@docs
IndexedMeanfieldNoiseEquations
```
```
2 changes: 1 addition & 1 deletion src/QuantumCumulants.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import QuantumOpticsBase: ⊗, tensor

export HilbertSpace, ProductSpace, ⊗, tensor,
QSym, QTerm, @qnumbers,
FockSpace, Destroy, Create,
FockSpace, Destroy, Create, GroundStateProjection,
NLevelSpace, Transition,
PauliSpace, Pauli, SpinSpace, Spin,
MeanfieldEquations,
Expand Down
67 changes: 60 additions & 7 deletions src/fock.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,31 @@ struct Create{H<:HilbertSpace,S,A,M} <: QSym
end
end

for T in (:Create, :Destroy)
"""
GroundStateProjection <: QSym

Bosonic operator on a [`FockSpace`](@ref) representing the quantum harmonic
oscillator ground state projection.

Warning: The ground state projection is not meant to be used in the cumulant
expansion.
"""
struct GroundStateProjection{H<:HilbertSpace,S,A,M} <: QSym
hilbert::H
name::S
aon::A
metadata::M
function GroundStateProjection{H,S,A,M}(hilbert::H, name::S, aon::A, metadata::M) where {H,S,A,M}
@assert has_hilbert(FockSpace,hilbert,aon)
new(hilbert,name,aon,metadata)
end
end

for T in (:Create, :Destroy, :GroundStateProjection)
@eval Base.isequal(a::$T, b::$T) = isequal(a.hilbert, b.hilbert) && isequal(a.name, b.name) && isequal(a.aon, b.aon)
end

for f in [:Destroy,:Create]
for f in [:Destroy,:Create, :GroundStateProjection]
@eval $(f)(hilbert::H, name::S, aon::A; metadata::M=NO_METADATA) where {H,S,A,M} = $(f){H,S,A,M}(hilbert,name,aon,metadata)
@eval $(f)(hilbert::FockSpace, name; metadata=NO_METADATA) = $(f)(hilbert,name,1; metadata)
@eval function $(f)(hilbert::H, name::S, aon::A; metadata::M=NO_METADATA) where {H<:ProductSpace,S,A<:Int,M}
Expand Down Expand Up @@ -75,6 +95,7 @@ end

Base.adjoint(op::Destroy) = Create(op.hilbert,op.name,acts_on(op); op.metadata)
Base.adjoint(op::Create) = Destroy(op.hilbert,op.name,acts_on(op); op.metadata)
Base.adjoint(op::GroundStateProjection) = op

# Commutation relation in simplification
function *(a::Destroy,b::Create)
Expand All @@ -89,11 +110,43 @@ function *(a::Destroy,b::Create)
return QMul(1, [b,a])
end
end
# ismergeable(::Destroy,::Create) = true

# TODO: test if faster; delete if and elseif in *-function above?
function ismergeable(a::Destroy,b::Create)
function *(a::GroundStateProjection,b::GroundStateProjection)
check_hilbert(a,b)
aon_a = acts_on(a)
aon_b = acts_on(b)
return aon_a == aon_b
end
if aon_a == aon_b
return a
elseif aon_a < aon_b
return QMul(1, [a,b])
else
return QMul(1, [b,a])
end
end

for (T1,T2) in ((:Destroy, :GroundStateProjection), (:GroundStateProjection, :Create))
@eval function *(a::$T1,b::$T2)
check_hilbert(a,b)
aon_a = acts_on(a)
aon_b = acts_on(b)
if aon_a == aon_b
return 0
elseif aon_a < aon_b
return QMul(1, [a,b])
else
return QMul(1, [b,a])
end
end
end

for T1 in (:Destroy, :GroundStateProjection)
for T2 in (:Create, :GroundStateProjection)
# ismergeable(::$T1,::$T2) = true
# TODO: test if faster; delete if and elseif in *-function above?
@eval function ismergeable(a::$T1,b::$T2)
aon_a = acts_on(a)
aon_b = acts_on(b)
return aon_a == aon_b
end
end
end
4 changes: 4 additions & 0 deletions src/latexify_recipes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ function _postwalk_func(x)
elseif MacroTools.@capture(x, dagger(arg_))
s = "$(arg)^\\dagger"
return s
elseif MacroTools.@capture(x, GroundStateProjection(arg_))
s = "\\vert \\emptyset_$(arg) \\rangle \\langle \\emptyset_$(arg) \\vert"
return s
elseif MacroTools.@capture(x, Transition(arg_,i_,j_))
s = "{$(arg)}$(transition_idx_script[]){{$(i)$(j)}}"
return s
Expand Down Expand Up @@ -202,6 +205,7 @@ function _to_expression(x::Complex{Symbolics.Num}) # forward complex Nums to Sym
end
_to_expression(op::QSym) = op.name
_to_expression(op::Create) = :(dagger($(op.name)))
_to_expression(op::GroundStateProjection) = :(GroundStateProjection($(op.name)))
_to_expression(op::Transition) = :(Transition($(op.name),$(op.i),$(op.j)) )
xyz_sym=[:x,:y,:z]
_to_expression(op::Pauli) = :(Pauli($(op.name),$(xyz_sym[op.axis])))
Expand Down
1 change: 1 addition & 0 deletions src/printing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ end

Base.show(io::IO,x::QSym) = write(io, x.name)
Base.show(io::IO,x::Create) = write(io, string(x.name, "′"))
Base.show(io::IO,x::GroundStateProjection) = write(io, string("∅_", x.name))
Base.show(io::IO,x::Transition) = write(io, Symbol(x.name,x.i,x.j))
Base.show(io::IO,x::Pauli) = write(io, Symbol(x.name,xyz_sym[x.axis]))
Base.show(io::IO,x::Spin) = write(io, Symbol(x.name,xyz_sym[x.axis]))
Expand Down
12 changes: 12 additions & 0 deletions test/test_fock.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,26 @@ using Test
hf = FockSpace(:c)

a = Destroy(hf,:a)
P0 = GroundStateProjection(hf, :a)
ad = a'

@test !isequal(hash(a), hash(ad))
b = Destroy(hf,:b)
@test !isequal(hash(a), hash(b))
@test !isequal(hash(a), hash(P0))

@test isequal(a,ad')
@test isequal(simplify(a+a),2*a)
@test isequal(simplify(a/2 + 0.5*a),a)
@test isequal(a*a' , 1+a'*a)
@test isequal(simplify(a*a' + 1) , 2 + a'*a)
@test isequal(simplify(P0 + P0) , 2*P0)
@test isequal(simplify(P0^2) , P0)
@test isequal(simplify(a'*a*(a')^3*P0^2) , 3*(a')^3*P0)

@test isequal(simplify(-1*(a'*a + 1)*a + a) , -1*a'*a^2)
@test isequal(simplify(a'*a*a - a*a'*a) , -1*a)
@test isequal(simplify(P0 - P0) , 0)

# Single mode
ωc = 0.1313
Expand All @@ -34,11 +40,17 @@ da = simplify(1.0im*(H*a - a*H))
@test iszero(substitute(x*a, Dict(x=>0)))
@test isequal(substitute(x*a, Dict(x=>1)), a)
@test iszero(substitute(x*a, Dict(a=>0)))
@test iszero(substitute(x*P0, Dict(x=>0)))
@test isequal(substitute(x*P0, Dict(x=>1)), P0)
@test iszero(substitute(x*P0, Dict(P0=>0)))

# Test substitute by syms
@syms y
@test isequal(substitute(x*a, Dict(x=>y)), y*a)
@test isequal(substitute(x*a, Dict(a=>y)), x*y)
@test isequal(substitute(x*(a+a'), Dict(x => y)), y*(a + a'))
@test isequal(substitute(x*P0, Dict(x=>y)), y*P0)
@test isequal(substitute(x*P0, Dict(P0=>y)), x*y)
@test isequal(substitute(x*(P0+a'*P0), Dict(x => y)), y*(P0 + a'*P0))

end # testset
Loading