Skip to content
Merged
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
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
69 changes: 48 additions & 21 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,48 +27,75 @@

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} = 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
expect(O::AbstractQuantumObject{OperatorQuantumObject}, ρ::AbstractVector{<:QuantumObject}) = expect.(Ref(O), ρ)
function expect(
O::AbstractVector{<:AbstractQuantumObject{OperatorQuantumObject,DimsType,<:Union{<:Hermitian{TF},<:Symmetric{TR}}}},
ρ::AbstractVector{<:QuantumObject},
) where {DimsType<:AbstractDimensions,TF<:Number,TR<:Real}
return real(tr(O * ρ))
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::QuantumObject{OperatorQuantumObject}, ρ::Vector{<:QuantumObject})
_expect = _ρ -> expect(O, _ρ)
return _expect.(ρ)
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"""
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