Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased](https://github.com/qutip/QuantumToolbox.jl/tree/main)

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

## [v0.25.0]
Release date: 2025-01-20
Expand Down Expand Up @@ -85,4 +86,6 @@ Release date: 2024-11-13
[#360]: https://github.com/qutip/QuantumToolbox.jl/issues/360
[#370]: https://github.com/qutip/QuantumToolbox.jl/issues/370
[#371]: https://github.com/qutip/QuantumToolbox.jl/issues/371
[#374]: https://github.com/qutip/QuantumToolbox.jl/issues/374
[#375]: https://github.com/qutip/QuantumToolbox.jl/issues/375
[#376]: https://github.com/qutip/QuantumToolbox.jl/issues/376
70 changes: 50 additions & 20 deletions src/qobj/functions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
ket2dm::QuantumObject{OperatorQuantumObject}) = ρ

@doc raw"""
expect(O::AbstractQuantumObject, ψ::Union{QuantumObject,Vector{QuantumObject}})
expect(O::Union{AbstractQuantumObject,Vector{AbstractQuantumObject}}, ψ::Union{QuantumObject,Vector{QuantumObject}})
Expectation value of the [`Operator`](@ref) `O` with the state `ψ`. The state can be a [`Ket`](@ref), [`Bra`](@ref) or [`Operator`](@ref).
Expand All @@ -27,49 +27,79 @@
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)`.
Note that `ψ` can also be given as a list of [`QuantumObject`](@ref), it returns a list of expectation values.
!!! note "List of observables and states"
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.
# Examples
```jldoctest
julia> ψ = 1 / √2 * (fock(10,2) + fock(10,4));
julia> ψ1 = 1 / √2 * (fock(10,2) + fock(10,4));
julia> ψ2 = coherent(10, 0.6 + 0.8im);
julia> a = destroy(10);
julia> expect(a' * a, ψ) |> round
julia> expect(a' * a, ψ1) |> round
3.0 + 0.0im
julia> expect(Hermitian(a' * a), ψ) |> round
julia> expect(Hermitian(a' * a), ψ1) |> round
3.0
julia> round.(expect([a' * a, a' + a, a], [ψ1, ψ2]), digits = 1)
3×2 Matrix{ComplexF64}:
3.0+0.0im 1.0+0.0im
0.0+0.0im 1.2-0.0im
0.0+0.0im 0.6+0.8im
```
"""
function expect(O::AbstractQuantumObject{OperatorQuantumObject}, ψ::QuantumObject{KetQuantumObject})
return dot.data, O.data, ψ.data)
end
expect(O::AbstractQuantumObject{OperatorQuantumObject}, ψ::QuantumObject{KetQuantumObject}) =
dot.data, O.data, ψ.data)
expect(O::AbstractQuantumObject{OperatorQuantumObject}, ψ::QuantumObject{BraQuantumObject}) = expect(O, ψ')
expect(O::QuantumObject{OperatorQuantumObject}, ρ::QuantumObject{OperatorQuantumObject}) = tr(O * ρ)
function expect(
expect(
O::QuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}},
ψ::QuantumObject{KetQuantumObject},
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
return real(dot.data, O.data, ψ.data))
end
function expect(
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = real(dot.data, O.data, ψ.data))
expect(

Check warning on line 63 in src/qobj/functions.jl

View check run for this annotation

Codecov / codecov/patch

src/qobj/functions.jl#L63

Added line #L63 was not covered by tests
O::QuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}},
ψ::QuantumObject{BraQuantumObject},
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
return real(expect(O, ψ'))
end
function expect(
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = real(expect(O, ψ'))
expect(
O::QuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}},
ρ::QuantumObject{OperatorQuantumObject},
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
return real(tr(O * ρ))
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = real(tr(O * ρ))
expect(
O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}}},
ρ::QuantumObject,
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real} = expect.(O, Ref(ρ))
function expect(O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject}}, ρ::QuantumObject)
result = Vector{ComplexF64}(undef, length(O))
result .= expect.(O, Ref(ρ))
return result
end
function expect(O::QuantumObject{OperatorQuantumObject}, ρ::Vector{<:QuantumObject})
function expect(O::AbstractQuantumObject{OperatorQuantumObject}, ρ::AbstractVector{<:QuantumObject})
_expect =-> expect(O, _ρ)
return _expect.(ρ)
end
function expect(
O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}}},
ρ::AbstractVector{<:QuantumObject},
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
N_ops = length(O)
result = Matrix{Float64}(undef, N_ops, length(ρ))
for i in 1:N_ops
result[i, :] .= expect.(Ref(O[i]), ρ)
end
return result
end
function expect(O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject}}, ρ::AbstractVector{<:QuantumObject})
N_ops = length(O)
result = Matrix{ComplexF64}(undef, N_ops, length(ρ))
for i in 1:N_ops
result[i, :] .= expect.(Ref(O[i]), ρ)
end
return result
end

@doc raw"""
variance(O::QuantumObject, ψ::Union{QuantumObject,Vector{QuantumObject}})
Expand Down
18 changes: 18 additions & 0 deletions test/core-test/quantum_objects.jl
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,18 @@
ψlist = [normalize!(basis(N, 4) + x * basis(N, 3)) for x in xlist]
@test all(expect(a', ψlist) .≈ xlist)

# when input is a vector of observables
ρlist = Hermitian.(ket2dm.(ψlist)) # an alternative way to calculate expectation values for a list of density matrices
Olist1 = [a' * a, a' + a, a]
Olist2 = [Hermitian(a' * a), Hermitian(a' + a)]
exp_val_1 = expect(Olist1, ψlist)
exp_val_2 = expect(Olist2, ψlist)
@test size(exp_val_1) == (3, 4)
@test size(exp_val_2) == (2, 4)
@test all(exp_val_1[1, :] .≈ exp_val_2[1, :] .≈ expect(ρlist, a' * a))
@test all(exp_val_1[2, :] .≈ exp_val_2[2, :] .≈ expect(ρlist, a' + a))
@test all(exp_val_1[3, :] .≈ expect(a, ρlist))

@testset "Type Inference (expect)" begin
@inferred expect(a, ψ)
@inferred expect(a, ψ')
Expand All @@ -488,6 +500,12 @@
@inferred variance(a, ρ)
@inferred expect(a, ψlist)
@inferred variance(a, ψlist)
@inferred expect(ρlist, a)
@inferred expect(Olist1, ψ)
@inferred expect(Olist1, ψ')
@inferred expect(Olist1, ρ)
@inferred expect(Olist1, ψlist)
@inferred expect(Olist2, ψlist)
end
end

Expand Down
Loading