diff --git a/docs/src/api.md b/docs/src/api.md index 317acd82..42fab085 100644 --- a/docs/src/api.md +++ b/docs/src/api.md @@ -31,6 +31,7 @@ issuper size eltype length +sqrtm LinearAlgebra.tr LinearAlgebra.svdvals LinearAlgebra.norm @@ -55,6 +56,7 @@ negativity entropy_vn entanglement expect +fidelity wigner get_coherence n_th diff --git a/src/general_functions.jl b/src/general_functions.jl index 3178dc76..fad48c7a 100644 --- a/src/general_functions.jl +++ b/src/general_functions.jl @@ -1,6 +1,6 @@ export get_data, get_coherence, expect, ptrace export mat2vec, vec2mat -export entropy_vn, entanglement, tracedist +export entropy_vn, entanglement, tracedist, fidelity export gaussian, n_th export row_major_reshape, tidyup, tidyup!, meshgrid, sparse_to_dense, dense_to_sparse @@ -311,6 +311,37 @@ function expect( return ishermitian(O) ? real(tr(O * ρ)) : tr(O * ρ) end +@doc raw""" + fidelity(ρ::QuantumObject, σ::QuantumObject) + +Calculate the fidelity of two [`QuantumObject`](@ref): +``F(\rho, \sigma) = \textrm{Tr} \sqrt{\sqrt{\rho} \sigma \sqrt{\rho}}`` + +Here, the definition is from Nielsen & Chuang, "Quantum Computation and Quantum Information". It is the square root of the fidelity defined in R. Jozsa, Journal of Modern Optics, 41:12, 2315 (1994). + +Note that `ρ` and `σ` must be either [`Ket`](@ref) or [`Operator`](@ref). +""" +function fidelity( + ρ::QuantumObject{<:AbstractArray{T1},OperatorQuantumObject}, + σ::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject}, +) where {T1,T2} + sqrt_ρ = sqrt(ρ) + eigval = abs.(eigvals(sqrt_ρ * σ * sqrt_ρ)) + return sum(sqrt, eigval) +end +fidelity( + ρ::QuantumObject{<:AbstractArray{T1},OperatorQuantumObject}, + ψ::QuantumObject{<:AbstractArray{T2},KetQuantumObject}, +) where {T1,T2} = sqrt(abs(expect(ρ, ψ))) +fidelity( + ψ::QuantumObject{<:AbstractArray{T1},KetQuantumObject}, + σ::QuantumObject{<:AbstractArray{T2},OperatorQuantumObject}, +) where {T1,T2} = fidelity(σ, ψ) +fidelity( + ψ::QuantumObject{<:AbstractArray{T1},KetQuantumObject}, + ϕ::QuantumObject{<:AbstractArray{T2},KetQuantumObject}, +) where {T1,T2} = abs(dot(ψ, ϕ)) + @doc raw""" get_coherence(ψ::QuantumObject) diff --git a/src/quantum_object.jl b/src/quantum_object.jl index ba5e7da8..c67c5965 100644 --- a/src/quantum_object.jl +++ b/src/quantum_object.jl @@ -9,6 +9,7 @@ export QuantumObjectType, export Bra, Ket, Operator, OperatorBra, OperatorKet, SuperOperator export isket, isbra, isoper, isoperbra, isoperket, issuper, ket2dm +export sqrtm export tensor, ⊗ abstract type AbstractQuantumObject end @@ -741,7 +742,17 @@ LinearAlgebra.rmul!(B::QuantumObject{<:AbstractArray}, a::Number) = (rmul!(B.dat @inline LinearAlgebra.mul!(y::AbstractVector{Ty}, A::QuantumObject{<:AbstractMatrix{Ta}}, x, α, β) where {Ty,Ta} = mul!(y, A.data, x, α, β) -LinearAlgebra.sqrt(A::QuantumObject{<:AbstractArray{T}}) where {T} = QuantumObject(sqrt(A.data), A.type, A.dims) +LinearAlgebra.sqrt(A::QuantumObject{<:AbstractArray{T}}) where {T} = + QuantumObject(sqrt(sparse_to_dense(A.data)), A.type, A.dims) + +@doc raw""" + sqrtm(A::QuantumObject) + +Matrix square root of [`Operator`](@ref) type of [`QuantumObject`](@ref) + +Note that for other types of [`QuantumObject`](@ref) use `sprt(A)` instead. +""" +sqrtm(A::QuantumObject{<:AbstractArray{T},OperatorQuantumObject}) where {T} = sqrt(A) LinearAlgebra.exp(A::QuantumObject{<:AbstractMatrix{T}}) where {T} = QuantumObject(dense_to_sparse(exp(A.data)), A.type, A.dims) diff --git a/test/quantum_objects.jl b/test/quantum_objects.jl index f7097feb..6e70f41f 100644 --- a/test/quantum_objects.jl +++ b/test/quantum_objects.jl @@ -238,6 +238,16 @@ @test tracedist(ψz1, ρz0) ≈ 1.0 @test tracedist(ρz0, ρz1) ≈ 1.0 + # sqrtm (sqrt) and fidelity + M = sprand(ComplexF64, 5, 5, 0.5) + M0 = Qobj(M * M') + ψ1 = Qobj(rand(ComplexF64, 5)) + ψ2 = Qobj(rand(ComplexF64, 5)) + M1 = ψ1 * ψ1' + @test sqrtm(M0) ≈ sqrtm(sparse_to_dense(M0)) + @test isapprox(fidelity(M0, M1), fidelity(ψ1, M0); atol = 1e-6) + @test isapprox(fidelity(ψ1, ψ2), fidelity(ket2dm(ψ1), ket2dm(ψ2)); atol = 1e-6) + # Broadcasting a = destroy(20) for op in ((+), (-), (*), (^))