Skip to content

Commit 2f0ce8e

Browse files
authored
Support a list of observables for expect (#376)
1 parent 9cc0224 commit 2f0ce8e

File tree

3 files changed

+69
-21
lines changed

3 files changed

+69
-21
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased](https://github.com/qutip/QuantumToolbox.jl/tree/main)
99

1010
- Fix Dynamical Fock Dimension states saving due to wrong saving of dimensions. ([#375])
11+
- Support a list of observables for `expect`. ([#374], [#376])
1112

1213
## [v0.25.0]
1314
Release date: 2025-01-20
@@ -85,4 +86,6 @@ Release date: 2024-11-13
8586
[#360]: https://github.com/qutip/QuantumToolbox.jl/issues/360
8687
[#370]: https://github.com/qutip/QuantumToolbox.jl/issues/370
8788
[#371]: https://github.com/qutip/QuantumToolbox.jl/issues/371
89+
[#374]: https://github.com/qutip/QuantumToolbox.jl/issues/374
8890
[#375]: https://github.com/qutip/QuantumToolbox.jl/issues/375
91+
[#376]: https://github.com/qutip/QuantumToolbox.jl/issues/376

src/qobj/functions.jl

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ket2dm(ψ::QuantumObject{KetQuantumObject}) = ψ * ψ'
1717
ket2dm::QuantumObject{OperatorQuantumObject}) = ρ
1818

1919
@doc raw"""
20-
expect(O::AbstractQuantumObject, ψ::Union{QuantumObject,Vector{QuantumObject}})
20+
expect(O::Union{AbstractQuantumObject,Vector{AbstractQuantumObject}}, ψ::Union{QuantumObject,Vector{QuantumObject}})
2121
2222
Expectation value of the [`Operator`](@ref) `O` with the state `ψ`. The state can be a [`Ket`](@ref), [`Bra`](@ref) or [`Operator`](@ref).
2323
@@ -27,48 +27,75 @@ If `ψ` is a density matrix ([`Operator`](@ref)), the function calculates ``\tex
2727
2828
The function returns a real number if `O` is of `Hermitian` type or `Symmetric` type, and returns a complex number otherwise. You can make an operator `O` hermitian by using `Hermitian(O)`.
2929
30-
Note that `ψ` can also be given as a list of [`QuantumObject`](@ref), it returns a list of expectation values.
30+
!!! note "List of observables and states"
31+
The observable `O` and state `ψ` can be given as a list of [`QuantumObject`](@ref), it returns a list of expectation values. If both of them are given as a list, it returns a `Matrix` of expectation values.
3132
3233
# Examples
3334
3435
```jldoctest
35-
julia> ψ = 1 / √2 * (fock(10,2) + fock(10,4));
36+
julia> ψ1 = 1 / √2 * (fock(10,2) + fock(10,4));
37+
38+
julia> ψ2 = coherent(10, 0.6 + 0.8im);
3639
3740
julia> a = destroy(10);
3841
39-
julia> expect(a' * a, ψ) |> round
42+
julia> expect(a' * a, ψ1) |> round
4043
3.0 + 0.0im
4144
42-
julia> expect(Hermitian(a' * a), ψ) |> round
45+
julia> expect(Hermitian(a' * a), ψ1) |> round
4346
3.0
47+
48+
julia> round.(expect([a' * a, a' + a, a], [ψ1, ψ2]), digits = 1)
49+
3×2 Matrix{ComplexF64}:
50+
3.0+0.0im 1.0+0.0im
51+
0.0+0.0im 1.2-0.0im
52+
0.0+0.0im 0.6+0.8im
4453
```
4554
"""
46-
function expect(O::AbstractQuantumObject{OperatorQuantumObject}, ψ::QuantumObject{KetQuantumObject})
47-
return dot.data, O.data, ψ.data)
48-
end
55+
expect(O::AbstractQuantumObject{OperatorQuantumObject}, ψ::QuantumObject{KetQuantumObject}) =
56+
dot.data, O.data, ψ.data)
4957
expect(O::AbstractQuantumObject{OperatorQuantumObject}, ψ::QuantumObject{BraQuantumObject}) = expect(O, ψ')
5058
expect(O::QuantumObject{OperatorQuantumObject}, ρ::QuantumObject{OperatorQuantumObject}) = tr(O * ρ)
51-
function expect(
59+
expect(
5260
O::QuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}},
5361
ψ::QuantumObject{KetQuantumObject},
54-
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
55-
return real(dot.data, O.data, ψ.data))
56-
end
57-
function expect(
62+
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = real(dot.data, O.data, ψ.data))
63+
expect(
5864
O::QuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}},
5965
ψ::QuantumObject{BraQuantumObject},
60-
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
61-
return real(expect(O, ψ'))
62-
end
63-
function expect(
66+
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = real(expect(O, ψ'))
67+
expect(
6468
O::QuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}},
6569
ρ::QuantumObject{OperatorQuantumObject},
70+
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = real(tr(O * ρ))
71+
expect(
72+
O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}}},
73+
ρ::QuantumObject,
74+
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = expect.(O, Ref(ρ))
75+
function expect(O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject}}, ρ::QuantumObject)
76+
result = Vector{ComplexF64}(undef, length(O))
77+
result .= expect.(O, Ref(ρ))
78+
return result
79+
end
80+
expect(O::AbstractQuantumObject{OperatorQuantumObject}, ρ::AbstractVector{<:QuantumObject}) = expect.(Ref(O), ρ)
81+
function expect(
82+
O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}}},
83+
ρ::AbstractVector{<:QuantumObject},
6684
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
67-
return real(tr(O * ρ))
85+
N_ops = length(O)
86+
result = Matrix{Float64}(undef, N_ops, length(ρ))
87+
for i in 1:N_ops
88+
result[i, :] .= expect.(Ref(O[i]), ρ)
89+
end
90+
return result
6891
end
69-
function expect(O::QuantumObject{OperatorQuantumObject}, ρ::Vector{<:QuantumObject})
70-
_expect =-> expect(O, _ρ)
71-
return _expect.(ρ)
92+
function expect(O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject}}, ρ::AbstractVector{<:QuantumObject})
93+
N_ops = length(O)
94+
result = Matrix{ComplexF64}(undef, N_ops, length(ρ))
95+
for i in 1:N_ops
96+
result[i, :] .= expect.(Ref(O[i]), ρ)
97+
end
98+
return result
7299
end
73100

74101
@doc raw"""

test/core-test/quantum_objects.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,18 @@
479479
ψlist = [normalize!(basis(N, 4) + x * basis(N, 3)) for x in xlist]
480480
@test all(expect(a', ψlist) .≈ xlist)
481481

482+
# when input is a vector of observables
483+
ρlist = Hermitian.(ket2dm.(ψlist)) # an alternative way to calculate expectation values for a list of density matrices
484+
Olist1 = [a' * a, a' + a, a]
485+
Olist2 = [Hermitian(a' * a), Hermitian(a' + a)]
486+
exp_val_1 = expect(Olist1, ψlist)
487+
exp_val_2 = expect(Olist2, ψlist)
488+
@test size(exp_val_1) == (3, 4)
489+
@test size(exp_val_2) == (2, 4)
490+
@test all(exp_val_1[1, :] .≈ exp_val_2[1, :] .≈ expect(ρlist, a' * a))
491+
@test all(exp_val_1[2, :] .≈ exp_val_2[2, :] .≈ expect(ρlist, a' + a))
492+
@test all(exp_val_1[3, :] .≈ expect(a, ρlist))
493+
482494
@testset "Type Inference (expect)" begin
483495
@inferred expect(a, ψ)
484496
@inferred expect(a, ψ')
@@ -488,6 +500,12 @@
488500
@inferred variance(a, ρ)
489501
@inferred expect(a, ψlist)
490502
@inferred variance(a, ψlist)
503+
@inferred expect(ρlist, a)
504+
@inferred expect(Olist1, ψ)
505+
@inferred expect(Olist1, ψ')
506+
@inferred expect(Olist1, ρ)
507+
@inferred expect(Olist1, ψlist)
508+
@inferred expect(Olist2, ψlist)
491509
end
492510
end
493511

0 commit comments

Comments
 (0)