diff --git a/docs/src/api.md b/docs/src/api.md index ad36a6f3..54f82300 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -87,6 +87,7 @@ eigsolve_al ```@docs ket2dm expect +variance LinearAlgebra.kron sparse_to_dense dense_to_sparse diff --git a/src/qobj/functions.jl b/src/qobj/functions.jl index 46a025e5..6dde41d6 100644 --- a/src/qobj/functions.jl +++ b/src/qobj/functions.jl @@ -3,7 +3,7 @@ Functions which manipulates QuantumObject =# export ket2dm -export expect +export expect, variance export sparse_to_dense, dense_to_sparse export vec2mat, mat2vec @@ -19,12 +19,13 @@ ket2dm(ρ::QuantumObject{<:AbstractArray{T},OperatorQuantumObject}) where {T} = @doc raw""" expect(O::QuantumObject, ψ::QuantumObject) -Expectation value of the operator `O` with the state `ψ`. The latter -can be a [`KetQuantumObject`](@ref), [`BraQuantumObject`](@ref) or a [`OperatorQuantumObject`](@ref). -If `ψ` is a density matrix, the function calculates ``\Tr \left[ \hat{O} \hat{\psi} \right]``, while if `ψ` -is a state, the function calculates ``\mel{\psi}{\hat{O}}{\psi}``. +Expectation value of the [`Operator`](@ref) `O` with the state `ψ`. The state can be a [`Ket`](@ref), [`Bra`](@ref) or [`Operator`](@ref). -The function returns a real number if the operator is hermitian, and returns a complex number otherwise. +If `ψ` is a [`Ket`](@ref) or [`Bra`](@ref), the function calculates ``\langle\psi|\hat{O}|\psi\rangle``. + +If `ψ` is a density matrix ([`Operator`](@ref)), the function calculates ``\textrm{Tr} \left[ \hat{O} \hat{\psi} \right]`` + +The function returns a real number if `O` is hermitian, and returns a complex number otherwise. # Examples @@ -60,6 +61,20 @@ function expect( return ishermitian(O) ? real(tr(O * ρ)) : tr(O * ρ) end +@doc raw""" + variance(O::QuantumObject, ψ::QuantumObject) + +Variance of the [`Operator`](@ref) `O`: ``\langle\hat{O}^2\rangle - \langle\hat{O}\rangle^2``, + +where ``\langle\hat{O}\rangle`` is the expectation value of `O` with the state `ψ` (see also [`expect`](@ref)), and the state `ψ` can be a [`Ket`](@ref), [`Bra`](@ref) or [`Operator`](@ref). + +The function returns a real number if `O` is hermitian, and returns a complex number otherwise. +""" +variance( + O::QuantumObject{<:AbstractArray{T1},OperatorQuantumObject}, + ψ::QuantumObject{<:AbstractArray{T2}}, +) where {T1,T2} = expect(O^2, ψ) - expect(O, ψ)^2 + @doc raw""" sparse_to_dense(A::QuantumObject) diff --git a/test/quantum_objects.jl b/test/quantum_objects.jl index 0ea0a573..e52b773f 100644 --- a/test/quantum_objects.jl +++ b/test/quantum_objects.jl @@ -249,7 +249,7 @@ @test opstring == "Quantum Object: type=OperatorBra dims=$ψ2_dims size=$ψ2_size\n$datastring" end - @testset "Matrix Element" begin + @testset "matrix element" begin H = Qobj([1 2; 3 4]) L = liouvillian(H) s0 = Qobj(basis(4, 0).data; type = OperatorKet) @@ -321,10 +321,13 @@ end @testset "expectation value" begin + # expect and variance N = 10 a = destroy(N) - ψ = normalize(fock(N, 3) + 1im * fock(N, 4)) + ψ = rand_ket(N) @test expect(a, ψ) ≈ expect(a, ψ') + @test variance(a, ψ) ≈ expect(a^2, ψ) - expect(a, ψ)^2 + ψ = fock(N, 3) @test norm(ψ' * a) ≈ 2 @test expect(a' * a, ψ' * a) ≈ 16