From 4ecf69438de1cb4e4cce56aa60eec826aaad6b53 Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Thu, 20 Feb 2025 13:48:51 +0900 Subject: [PATCH 1/5] introduce `concurrence` --- docs/src/resources/api.md | 3 ++- src/entropy.jl | 29 +++++++++++++++++++-- test/core-test/entropy_and_metric.jl | 39 +++++++++++++++++++++------- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/docs/src/resources/api.md b/docs/src/resources/api.md index 4a5ead010..f965ff24f 100644 --- a/docs/src/resources/api.md +++ b/docs/src/resources/api.md @@ -259,6 +259,8 @@ entropy_linear entropy_mutual entropy_conditional entanglement +concurrence +negativity tracedist fidelity ``` @@ -282,7 +284,6 @@ BlockDiagonalForm ```@docs wigner -negativity ``` ## [Linear Maps](@id doc-API:Linear-Maps) diff --git a/src/entropy.jl b/src/entropy.jl index c9f2555ab..1ffe1f1a9 100644 --- a/src/entropy.jl +++ b/src/entropy.jl @@ -3,7 +3,7 @@ Entropy related functions. =# export entropy_vn, entropy_relative, entropy_linear, entropy_mutual, entropy_conditional -export entanglement +export entanglement, concurrence @doc raw""" entropy_vn(ρ::QuantumObject; base::Int=0, tol::Real=1e-15) @@ -121,7 +121,7 @@ function entropy_relative( # the relative entropy is guaranteed to be ≥ 0 # so we calculate the value to 0 to avoid small violations of the lower bound. - return max(0.0, dot(p_vals, log_p) - dot(p, P, log_q)) + return max(0.0, dot(p_vals, log_p) - dot(p, P, log_q)) # use 0.0 to make sure it always return value in Float-type end @doc raw""" @@ -209,3 +209,28 @@ function entanglement( val = entropy_vn(ρ_tr; kwargs...) return (val > 0) * val end + +@doc raw""" + concurrence(ρ::QuantumObject) + +Calculate the [concurrence](https://en.wikipedia.org/wiki/Concurrence_(quantum_computing)) for a two-qubit state. + +# Notes + +- `ρ` can be either a [`Ket`](@ref) or an [`Operator`](@ref). +""" +function concurrence(ρ::QuantumObject{OpType}) where {OpType<:Union{KetQuantumObject,OperatorQuantumObject}} + (ρ.dimensions == Dimensions((Space(2), Space(2)))) || throw(ArgumentError("The `concurrence` only support for a two-qubit state, invalid dims = $(_get_dims_string(ρ.dimensions)).")) + + _ρ = ket2dm(ρ).data + σy = sigmay() + σyσy = kron(σy, σy).data + ρ_tilde = σyσy * conj(_ρ) * σyσy + + # we use the alternative way to calculate concurrence (more efficient) + # calculate the square root of each eigenvalues (in decreasing order) of the non-Hermitian matrix: ρ * ρ_tilde + # note that we add abs here to avoid problems with sqrt for very small negative numbers + λ = sqrt.(abs.(real(eigvals(_ρ * ρ_tilde; sortby = x -> -real(x))))) + + return max(0.0, λ[1] - λ[2] - λ[3] - λ[4]) # use 0.0 to make sure it always return value in Float-type +end \ No newline at end of file diff --git a/test/core-test/entropy_and_metric.jl b/test/core-test/entropy_and_metric.jl index 5225c5ea2..6b4f4a37b 100644 --- a/test/core-test/entropy_and_metric.jl +++ b/test/core-test/entropy_and_metric.jl @@ -51,17 +51,38 @@ end end -@testset "Entanglement" begin - g = fock(2, 1) - e = fock(2, 0) - state = normalize(kron(g, e) + kron(e, g)) - rho = state * state' - @test entanglement(state, 1) / log(2) ≈ 1 - @test entanglement(rho, 1) / log(2) ≈ 1 +@testset "entanglement and concurrence" begin + # bell state + ψb = bell_state(Val(1), Val(0)) + ρb = ket2dm(ψb) + @test entanglement(ψb, 1) / log(2) ≈ 1 + @test entanglement(ρb, 1) / log(2) ≈ 1 + @test concurrence(ψb) ≈ 1 + @test concurrence(ρb) ≈ 1 + + # separable pure state + ψs = kron(rand_ket(2), rand_ket(2)) + @test entanglement(ψs, 1) + 1 ≈ 1 + @test entanglement(ψs, 2) + 1 ≈ 1 + @test concurrence(ψs) + 1 ≈ 1 + + # this only works for "pure" two-qubit states + ψr = rand_ket((2, 2)) # might be an entangled two-qubit state + val = concurrence(ψr) + @test isapprox(val, sqrt(2 * entropy_linear(ptrace(ψr, 1))); atol = 1e-5) # √(2 * (1 - Tr(ρA^2))) + @test isapprox(val, sqrt(2 * entropy_linear(ptrace(ψr, 2))); atol = 1e-5) # √(2 * (1 - Tr(ρB^2))) + + @test_throws ArgumentError concurrence(rand_dm(4)) + @test_throws ArgumentError concurrence(rand_dm((2, 3))) @testset "Type Stability (entanglement)" begin - @inferred entanglement(state, 1) - @inferred entanglement(rho, 1) + @inferred entanglement(ψb, 1) + @inferred entanglement(ρb, 1) + end + + @testset "Type Stability (concurrence)" begin + @inferred concurrence(ψb) + @inferred concurrence(ρb) end end From bfe1f99c5d88dee1871c200ba67895f3b18b609e Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Thu, 20 Feb 2025 14:11:25 +0900 Subject: [PATCH 2/5] fix `entanglement` --- src/entropy.jl | 22 ++++++++++++++++------ test/core-test/entropy_and_metric.jl | 3 ++- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/entropy.jl b/src/entropy.jl index 1ffe1f1a9..4676ea87d 100644 --- a/src/entropy.jl +++ b/src/entropy.jl @@ -195,7 +195,7 @@ Calculates the [entanglement entropy](https://en.wikipedia.org/wiki/Entropy_of_e # Notes -- `ρ` can be either a [`Ket`](@ref) or an [`Operator`](@ref). +- `ρ` can be either a [`Ket`](@ref) or an [`Operator`](@ref). But should be a pure state. - `sel` specifies the indices of the remaining sub-system. See also [`ptrace`](@ref). - `kwargs` are the keyword arguments for calculating Von Neumann entropy. See also [`entropy_vn`](@ref). """ @@ -204,10 +204,16 @@ function entanglement( sel::Union{Int,AbstractVector{Int},Tuple}, kwargs..., ) where {OpType<:Union{KetQuantumObject,OperatorQuantumObject}} - _ρ = normalize(ρ) - ρ_tr = ptrace(_ρ, sel) + p = purity(ρ) + isapprox(p, 1; atol = 1e-2) || throw( + ArgumentError( + "The entanglement entropy only works for normalized pure state, the purity of the given state: $(p) ≉ 1", + ), + ) + + ρ_tr = ptrace(ρ, sel) val = entropy_vn(ρ_tr; kwargs...) - return (val > 0) * val + return max(0.0, val) # use 0.0 to make sure it always return value in Float-type end @doc raw""" @@ -220,7 +226,11 @@ Calculate the [concurrence](https://en.wikipedia.org/wiki/Concurrence_(quantum_c - `ρ` can be either a [`Ket`](@ref) or an [`Operator`](@ref). """ function concurrence(ρ::QuantumObject{OpType}) where {OpType<:Union{KetQuantumObject,OperatorQuantumObject}} - (ρ.dimensions == Dimensions((Space(2), Space(2)))) || throw(ArgumentError("The `concurrence` only support for a two-qubit state, invalid dims = $(_get_dims_string(ρ.dimensions)).")) + (ρ.dimensions == Dimensions((Space(2), Space(2)))) || throw( + ArgumentError( + "The `concurrence` only works for a two-qubit state, invalid dims = $(_get_dims_string(ρ.dimensions)).", + ), + ) _ρ = ket2dm(ρ).data σy = sigmay() @@ -233,4 +243,4 @@ function concurrence(ρ::QuantumObject{OpType}) where {OpType<:Union{KetQuantumO λ = sqrt.(abs.(real(eigvals(_ρ * ρ_tilde; sortby = x -> -real(x))))) return max(0.0, λ[1] - λ[2] - λ[3] - λ[4]) # use 0.0 to make sure it always return value in Float-type -end \ No newline at end of file +end diff --git a/test/core-test/entropy_and_metric.jl b/test/core-test/entropy_and_metric.jl index 6b4f4a37b..746a491e7 100644 --- a/test/core-test/entropy_and_metric.jl +++ b/test/core-test/entropy_and_metric.jl @@ -72,8 +72,9 @@ end @test isapprox(val, sqrt(2 * entropy_linear(ptrace(ψr, 1))); atol = 1e-5) # √(2 * (1 - Tr(ρA^2))) @test isapprox(val, sqrt(2 * entropy_linear(ptrace(ψr, 2))); atol = 1e-5) # √(2 * (1 - Tr(ρB^2))) - @test_throws ArgumentError concurrence(rand_dm(4)) + @test_throws ArgumentError entanglement(rand_dm((2, 2)), 1) @test_throws ArgumentError concurrence(rand_dm((2, 3))) + @test_throws ArgumentError concurrence(rand_dm(4)) @testset "Type Stability (entanglement)" begin @inferred entanglement(ψb, 1) From 0c7bba2efac2b6e34f308759a6f94be4f6e5ddf0 Mon Sep 17 00:00:00 2001 From: Yi-Te Huang Date: Thu, 20 Feb 2025 14:13:19 +0900 Subject: [PATCH 3/5] update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d96870bfa..6cd7affe9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `entropy_mutual` - `entropy_conditional` - `entropy_relative` +- Fix `entanglement` and introduce `concurrence`. ([#418], [#419]) ## [v0.27.0] Release date: 2025-02-14 @@ -155,3 +156,5 @@ Release date: 2024-11-13 [#411]: https://github.com/qutip/QuantumToolbox.jl/issues/411 [#413]: https://github.com/qutip/QuantumToolbox.jl/issues/413 [#416]: https://github.com/qutip/QuantumToolbox.jl/issues/416 +[#418]: https://github.com/qutip/QuantumToolbox.jl/issues/418 +[#419]: https://github.com/qutip/QuantumToolbox.jl/issues/419 From 52c14321ba78c79f47b100c3ca2e4a141a496d52 Mon Sep 17 00:00:00 2001 From: Yi-Te Huang <44385685+ytdHuang@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:21:36 +0900 Subject: [PATCH 4/5] [no ci] fix changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cd7affe9..7226dbdc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,12 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Change save callbacks from `PresetTimeCallback` to `FunctionCallingCallback`. ([#410]) - Align `eigenstates` and `eigenenergies` to QuTiP. ([#411]) - Introduce `vector_to_operator` and `operator_to_vector`. ([#413]) -- Introduce some entropy related functions. ([#416]) +- Introduce some entropy related functions. ([#414], [#416]) - `entropy_linear` - `entropy_mutual` - `entropy_conditional` - `entropy_relative` -- Fix `entanglement` and introduce `concurrence`. ([#418], [#419]) +- Fix `entanglement` and introduce `concurrence`. ([#414], [#418], [#419]) ## [v0.27.0] Release date: 2025-02-14 @@ -155,6 +155,7 @@ Release date: 2024-11-13 [#410]: https://github.com/qutip/QuantumToolbox.jl/issues/410 [#411]: https://github.com/qutip/QuantumToolbox.jl/issues/411 [#413]: https://github.com/qutip/QuantumToolbox.jl/issues/413 +[#414]: https://github.com/qutip/QuantumToolbox.jl/issues/414 [#416]: https://github.com/qutip/QuantumToolbox.jl/issues/416 [#418]: https://github.com/qutip/QuantumToolbox.jl/issues/418 [#419]: https://github.com/qutip/QuantumToolbox.jl/issues/419 From 61a1e29b25a145e6047e9839f054968f0bf6634f Mon Sep 17 00:00:00 2001 From: Yi-Te Huang <44385685+ytdHuang@users.noreply.github.com> Date: Thu, 20 Feb 2025 15:24:18 +0900 Subject: [PATCH 5/5] minor changes --- src/entropy.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/entropy.jl b/src/entropy.jl index 4676ea87d..59a992185 100644 --- a/src/entropy.jl +++ b/src/entropy.jl @@ -1,5 +1,5 @@ #= -Entropy related functions. +Entropy related functions and some entanglement measures. =# export entropy_vn, entropy_relative, entropy_linear, entropy_mutual, entropy_conditional