Skip to content

Commit 226c0bc

Browse files
committed
add GroundStateProjection operator for FockSpace
1 parent 95499fa commit 226c0bc

File tree

6 files changed

+82
-9
lines changed

6 files changed

+82
-9
lines changed

docs/src/api.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ Destroy
6868
Create
6969
```
7070

71+
```@docs
72+
GroundStateProjection
73+
```
74+
7175
```@docs
7276
Transition
7377
```
@@ -330,4 +334,4 @@ MeanfieldNoiseEquations
330334

331335
```@docs
332336
IndexedMeanfieldNoiseEquations
333-
```
337+
```

src/QuantumCumulants.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import QuantumOpticsBase: ⊗, tensor
2020

2121
export HilbertSpace, ProductSpace, , tensor,
2222
QSym, QTerm, @qnumbers,
23-
FockSpace, Destroy, Create,
23+
FockSpace, Destroy, Create, GroundStateProjection,
2424
NLevelSpace, Transition,
2525
PauliSpace, Pauli, SpinSpace, Spin,
2626
MeanfieldEquations,

src/fock.jl

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,31 @@ struct Create{H<:HilbertSpace,S,A,M} <: QSym
4343
end
4444
end
4545

46-
for T in (:Create, :Destroy)
46+
"""
47+
GroundStateProjection <: QSym
48+
49+
Bosonic operator on a [`FockSpace`](@ref) representing the quantum harmonic
50+
oscillator ground state projection.
51+
52+
Warning: The ground state projection is not meant to be used in the cumulant
53+
expansion.
54+
"""
55+
struct GroundStateProjection{H<:HilbertSpace,S,A,M} <: QSym
56+
hilbert::H
57+
name::S
58+
aon::A
59+
metadata::M
60+
function GroundStateProjection{H,S,A,M}(hilbert::H, name::S, aon::A, metadata::M) where {H,S,A,M}
61+
@assert has_hilbert(FockSpace,hilbert,aon)
62+
new(hilbert,name,aon,metadata)
63+
end
64+
end
65+
66+
for T in (:Create, :Destroy, :GroundStateProjection)
4767
@eval Base.isequal(a::$T, b::$T) = isequal(a.hilbert, b.hilbert) && isequal(a.name, b.name) && isequal(a.aon, b.aon)
4868
end
4969

50-
for f in [:Destroy,:Create]
70+
for f in [:Destroy,:Create, :GroundStateProjection]
5171
@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)
5272
@eval $(f)(hilbert::FockSpace, name; metadata=NO_METADATA) = $(f)(hilbert,name,1; metadata)
5373
@eval function $(f)(hilbert::H, name::S, aon::A; metadata::M=NO_METADATA) where {H<:ProductSpace,S,A<:Int,M}
@@ -75,6 +95,7 @@ end
7595

7696
Base.adjoint(op::Destroy) = Create(op.hilbert,op.name,acts_on(op); op.metadata)
7797
Base.adjoint(op::Create) = Destroy(op.hilbert,op.name,acts_on(op); op.metadata)
98+
Base.adjoint(op::GroundStateProjection) = op
7899

79100
# Commutation relation in simplification
80101
function *(a::Destroy,b::Create)
@@ -89,11 +110,43 @@ function *(a::Destroy,b::Create)
89110
return QMul(1, [b,a])
90111
end
91112
end
92-
# ismergeable(::Destroy,::Create) = true
93113

94-
# TODO: test if faster; delete if and elseif in *-function above?
95-
function ismergeable(a::Destroy,b::Create)
114+
function *(a::GroundStateProjection,b::GroundStateProjection)
115+
check_hilbert(a,b)
96116
aon_a = acts_on(a)
97117
aon_b = acts_on(b)
98-
return aon_a == aon_b
99-
end
118+
if aon_a == aon_b
119+
return a
120+
elseif aon_a < aon_b
121+
return QMul(1, [a,b])
122+
else
123+
return QMul(1, [b,a])
124+
end
125+
end
126+
127+
for (T1,T2) in ((:Destroy, :GroundStateProjection), (:GroundStateProjection, :Create))
128+
@eval function *(a::$T1,b::$T2)
129+
check_hilbert(a,b)
130+
aon_a = acts_on(a)
131+
aon_b = acts_on(b)
132+
if aon_a == aon_b
133+
return 0
134+
elseif aon_a < aon_b
135+
return QMul(1, [a,b])
136+
else
137+
return QMul(1, [b,a])
138+
end
139+
end
140+
end
141+
142+
for T1 in (:Destroy, :GroundStateProjection)
143+
for T2 in (:Create, :GroundStateProjection)
144+
# ismergeable(::$T1,::$T2) = true
145+
# TODO: test if faster; delete if and elseif in *-function above?
146+
@eval function ismergeable(a::$T1,b::$T2)
147+
aon_a = acts_on(a)
148+
aon_b = acts_on(b)
149+
return aon_a == aon_b
150+
end
151+
end
152+
end

src/latexify_recipes.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ function _postwalk_func(x)
2525
return "\\mathbb{1}"
2626
elseif x==:im
2727
return :i
28+
elseif MacroTools.@capture(x, ground_state(arg_))
29+
s = "\\vert \\emptyset_$(arg) \\rangle \\langle \\emptyset_$(arg) \\vert"
2830
elseif MacroTools.@capture(x, dagger(arg_))
2931
s = "$(arg)^\\dagger"
3032
return s
@@ -202,6 +204,7 @@ function _to_expression(x::Complex{Symbolics.Num}) # forward complex Nums to Sym
202204
end
203205
_to_expression(op::QSym) = op.name
204206
_to_expression(op::Create) = :(dagger($(op.name)))
207+
_to_expression(op::GroundStateProjection) = :(ground_state($(op.name)))
205208
_to_expression(op::Transition) = :(Transition($(op.name),$(op.i),$(op.j)) )
206209
xyz_sym=[:x,:y,:z]
207210
_to_expression(op::Pauli) = :(Pauli($(op.name),$(xyz_sym[op.axis])))

src/printing.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ end
1313

1414
Base.show(io::IO,x::QSym) = write(io, x.name)
1515
Base.show(io::IO,x::Create) = write(io, string(x.name, ""))
16+
Base.show(io::IO,x::GroundStateProjection) = write(io, string("∅_", x.name))
1617
Base.show(io::IO,x::Transition) = write(io, Symbol(x.name,x.i,x.j))
1718
Base.show(io::IO,x::Pauli) = write(io, Symbol(x.name,xyz_sym[x.axis]))
1819
Base.show(io::IO,x::Spin) = write(io, Symbol(x.name,xyz_sym[x.axis]))

test/test_fock.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,26 @@ using Test
88
hf = FockSpace(:c)
99

1010
a = Destroy(hf,:a)
11+
P0 = GroundStateProjection(hf, :a)
1112
ad = a'
1213

1314
@test !isequal(hash(a), hash(ad))
1415
b = Destroy(hf,:b)
1516
@test !isequal(hash(a), hash(b))
17+
@test !isequal(hash(a), hash(P0))
1618

1719
@test isequal(a,ad')
1820
@test isequal(simplify(a+a),2*a)
1921
@test isequal(simplify(a/2 + 0.5*a),a)
2022
@test isequal(a*a' , 1+a'*a)
2123
@test isequal(simplify(a*a' + 1) , 2 + a'*a)
24+
@test isequal(simplify(P0 + P0) , 2*P0)
25+
@test isequal(simplify(P0^2) , P0)
26+
@test isequal(simplify(a'*a*(a')^3*P0^2) , 3*(a')^3*P0)
2227

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

2632
# Single mode
2733
ωc = 0.1313
@@ -34,11 +40,17 @@ da = simplify(1.0im*(H*a - a*H))
3440
@test iszero(substitute(x*a, Dict(x=>0)))
3541
@test isequal(substitute(x*a, Dict(x=>1)), a)
3642
@test iszero(substitute(x*a, Dict(a=>0)))
43+
@test iszero(substitute(x*P0, Dict(x=>0)))
44+
@test isequal(substitute(x*P0, Dict(x=>1)), P0)
45+
@test iszero(substitute(x*P0, Dict(P0=>0)))
3746

3847
# Test substitute by syms
3948
@syms y
4049
@test isequal(substitute(x*a, Dict(x=>y)), y*a)
4150
@test isequal(substitute(x*a, Dict(a=>y)), x*y)
4251
@test isequal(substitute(x*(a+a'), Dict(x => y)), y*(a + a'))
52+
@test isequal(substitute(x*P0, Dict(x=>y)), y*P0)
53+
@test isequal(substitute(x*P0, Dict(P0=>y)), x*y)
54+
@test isequal(substitute(x*(P0+a'*P0), Dict(x => y)), y*(P0 + a'*P0))
4355

4456
end # testset

0 commit comments

Comments
 (0)