From 87a99326a4f030be2b5123143f9b47f64449b748 Mon Sep 17 00:00:00 2001 From: Alberto Mercurio Date: Sun, 10 Nov 2024 03:32:52 +0100 Subject: [PATCH 1/2] Add doctest in all docstrings --- src/linear_maps.jl | 2 +- src/metrics.jl | 4 +- src/negativity.jl | 6 +- src/qobj/arithmetic_and_attributes.jl | 35 +++++++----- src/qobj/eigsolve.jl | 52 ++++++++++-------- src/qobj/functions.jl | 47 +++++----------- src/qobj/operators.jl | 8 +-- src/qobj/quantum_object.jl | 2 +- src/qobj/quantum_object_base.jl | 2 +- src/qobj/quantum_object_evo.jl | 64 +++++----------------- src/qobj/states.jl | 2 +- src/qobj/synonyms.jl | 79 ++++++++++----------------- src/utilities.jl | 8 +-- src/wigner.jl | 35 +++--------- 14 files changed, 132 insertions(+), 214 deletions(-) diff --git a/src/linear_maps.jl b/src/linear_maps.jl index 61ac4c96..a5e4082a 100644 --- a/src/linear_maps.jl +++ b/src/linear_maps.jl @@ -30,7 +30,7 @@ It is typically represented as a matrix with dimensions given by `size`, and thi As an example, we now define the linear map used in the [`eigsolve_al`](@ref) function for Arnoldi-Lindblad eigenvalue solver: -```julia-repl +```julia struct ArnoldiLindbladIntegratorMap{T,TS,TI} <: AbstractLinearMap{T,TS} elty::Type{T} size::TS diff --git a/src/metrics.jl b/src/metrics.jl index d8fd4f5e..0e2e5fd2 100644 --- a/src/metrics.jl +++ b/src/metrics.jl @@ -19,7 +19,7 @@ matrix ``\hat{\rho}``. # Examples Pure state: -``` +```jldoctest julia> ψ = fock(2,0) Quantum Object: type=Ket dims=[2] size=(2,) 2-element Vector{ComplexF64}: @@ -37,7 +37,7 @@ julia> entropy_vn(ρ, base=2) ``` Mixed state: -``` +```jldoctest julia> ρ = maximally_mixed_dm(2) Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=true 2×2 Diagonal{ComplexF64, Vector{ComplexF64}}: diff --git a/src/negativity.jl b/src/negativity.jl index 35d91c75..416020c8 100644 --- a/src/negativity.jl +++ b/src/negativity.jl @@ -17,7 +17,7 @@ and ``\Vert \hat{X} \Vert_1=\textrm{Tr}\sqrt{\hat{X}^\dagger \hat{X}}`` is the t # Examples -``` +```jldoctest julia> Ψ = bell_state(0, 0) Quantum Object: type=Ket dims=[2, 2] size=(4,) 4-element Vector{ComplexF64}: @@ -34,8 +34,8 @@ Quantum Object: type=Operator dims=[2, 2] size=(4, 4) ishermitian=true 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im -julia> negativity(ρ, 2) -0.4999999999999998 +julia> negativity(ρ, 2) |> round +0.0 ``` """ function negativity(ρ::QuantumObject, subsys::Int; logarithmic::Bool = false) diff --git a/src/qobj/arithmetic_and_attributes.jl b/src/qobj/arithmetic_and_attributes.jl index 5314d915..5a9c7d98 100644 --- a/src/qobj/arithmetic_and_attributes.jl +++ b/src/qobj/arithmetic_and_attributes.jl @@ -217,15 +217,15 @@ Note that this function only supports for [`Operator`](@ref) and [`SuperOperator # Examples -``` +```jldoctest julia> a = destroy(20) Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: -⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢ +⎡⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⎤ +⎢⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⎥ +⎢⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⎥ +⎢⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⎥ +⎣⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⎦ julia> tr(a' * a) 190.0 + 0.0im @@ -257,7 +257,7 @@ Return the standard vector `p`-norm or [Schatten](https://en.wikipedia.org/wiki/ # Examples -``` +```jldoctest julia> ψ = fock(10, 2) Quantum Object: type=Ket dims=[10] size=(10,) 10-element Vector{ComplexF64}: @@ -474,8 +474,9 @@ proj(ψ::QuantumObject{<:AbstractArray{T},BraQuantumObject}) where {T} = ψ' * Note that this function will always return [`Operator`](@ref). No matter the input [`QuantumObject`](@ref) is a [`Ket`](@ref), [`Bra`](@ref), or [`Operator`](@ref). # Examples + Two qubits in the state ``\ket{\psi} = \ket{e,g}``: -``` +```jldoctest julia> ψ = kron(fock(2,0), fock(2,1)) Quantum Object: type=Ket dims=[2, 2] size=(4,) 4-element Vector{ComplexF64}: @@ -492,7 +493,7 @@ Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=true ``` or in an entangled state ``\ket{\psi} = \frac{1}{\sqrt{2}} \left( \ket{e,e} + \ket{g,g} \right)``: -``` +```jldoctest julia> ψ = 1 / √2 * (kron(fock(2,0), fock(2,0)) + kron(fock(2,1), fock(2,1))) Quantum Object: type=Ket dims=[2, 2] size=(4,) 4-element Vector{ComplexF64}: @@ -693,12 +694,16 @@ Note that this method currently works for [`Ket`](@ref), [`Bra`](@ref), and [`Op If `order = [2, 1, 3]`, the Hilbert space structure will be re-arranged: ``\mathcal{H}_1 \otimes \mathcal{H}_2 \otimes \mathcal{H}_3 \rightarrow \mathcal{H}_2 \otimes \mathcal{H}_1 \otimes \mathcal{H}_3``. -``` -julia> ψ1 = fock(2, 0) -julia> ψ2 = fock(3, 1) -julia> ψ3 = fock(4, 2) -julia> ψ_123 = tensor(ψ1, ψ2, ψ3) -julia> permute(ψ_123, [2, 1, 3]) ≈ tensor(ψ2, ψ1, ψ3) +```jldoctest +julia> ψ1 = fock(2, 0); + +julia> ψ2 = fock(3, 1); + +julia> ψ3 = fock(4, 2); + +julia> ψ_123 = tensor(ψ1, ψ2, ψ3); + +julia> permute(ψ_123, (2, 1, 3)) ≈ tensor(ψ2, ψ1, ψ3) true ``` diff --git a/src/qobj/eigsolve.jl b/src/qobj/eigsolve.jl index 0c972a3f..63b4be99 100644 --- a/src/qobj/eigsolve.jl +++ b/src/qobj/eigsolve.jl @@ -30,10 +30,19 @@ A struct containing the eigenvalues, the eigenvectors, and some information from # Examples One can obtain the eigenvalues and the corresponding [`QuantumObject`](@ref)-type eigenvectors by: -``` -julia> result = eigenstates(sigmax()); +```jldoctest +julia> result = eigenstates(sigmax()) +EigsolveResult: type=Operator dims=[2] +values: +2-element Vector{ComplexF64}: + -1.0 + 0.0im + 1.0 + 0.0im +vectors: +2×2 Matrix{ComplexF64}: + -0.707107+0.0im 0.707107+0.0im + 0.707107+0.0im 0.707107+0.0im -julia> λ, ψ, T = result; +julia> λ, ψ, U = result; julia> λ 2-element Vector{ComplexF64}: @@ -41,11 +50,17 @@ julia> λ 1.0 + 0.0im julia> ψ -2-element Vector{QuantumObject{Vector{ComplexF64}, KetQuantumObject}}: - QuantumObject{Vector{ComplexF64}, KetQuantumObject}(ComplexF64[-0.7071067811865475 + 0.0im, 0.7071067811865475 + 0.0im], KetQuantumObject(), [2]) - QuantumObject{Vector{ComplexF64}, KetQuantumObject}(ComplexF64[0.7071067811865475 + 0.0im, 0.7071067811865475 + 0.0im], KetQuantumObject(), [2]) +2-element Vector{QuantumObject{Vector{ComplexF64}, KetQuantumObject, 1}}: + Quantum Object: type=Ket dims=[2] size=(2,) +2-element Vector{ComplexF64}: + -0.7071067811865475 + 0.0im + 0.7071067811865475 + 0.0im + Quantum Object: type=Ket dims=[2] size=(2,) +2-element Vector{ComplexF64}: + 0.7071067811865475 + 0.0im + 0.7071067811865475 + 0.0im -julia> T +julia> U 2×2 Matrix{ComplexF64}: -0.707107+0.0im 0.707107+0.0im 0.707107+0.0im 0.707107+0.0im @@ -411,27 +426,20 @@ end Calculates the eigenvalues and eigenvectors of the [`QuantumObject`](@ref) `A` using the Julia [LinearAlgebra](https://docs.julialang.org/en/v1/stdlib/LinearAlgebra/) package. -``` +```jldoctest julia> a = destroy(5); -julia> H = a + a' -Quantum Object: type=Operator dims=[5] size=(5, 5) ishermitian=true -5×5 SparseMatrixCSC{ComplexF64, Int64} with 8 stored entries: - ⋅ 1.0+0.0im ⋅ ⋅ ⋅ - 1.0+0.0im ⋅ 1.41421+0.0im ⋅ ⋅ - ⋅ 1.41421+0.0im ⋅ 1.73205+0.0im ⋅ - ⋅ ⋅ 1.73205+0.0im ⋅ 2.0+0.0im - ⋅ ⋅ ⋅ 2.0+0.0im ⋅ +julia> H = a + a'; julia> E, ψ, U = eigen(H) EigsolveResult: type=Operator dims=[5] values: -5-element Vector{Float64}: - -2.8569700138728 - -1.3556261799742608 - 1.3322676295501878e-15 - 1.3556261799742677 - 2.8569700138728056 +5-element Vector{ComplexF64}: + -2.8569700138728 + 0.0im + -1.3556261799742608 + 0.0im + 1.3322676295501878e-15 + 0.0im + 1.3556261799742677 + 0.0im + 2.8569700138728056 + 0.0im vectors: 5×5 Matrix{ComplexF64}: 0.106101+0.0im -0.471249-0.0im … 0.471249-0.0im 0.106101-0.0im diff --git a/src/qobj/functions.jl b/src/qobj/functions.jl index ef98af4d..1cc46391 100644 --- a/src/qobj/functions.jl +++ b/src/qobj/functions.jl @@ -31,7 +31,7 @@ Note that `ψ` can also be given as a list of [`QuantumObject`](@ref), it return # Examples -``` +```jldoctest julia> ψ = 1 / √2 * (fock(10,2) + fock(10,4)); julia> a = destroy(10); @@ -153,40 +153,23 @@ Returns the [Kronecker product](https://en.wikipedia.org/wiki/Kronecker_product) # Examples -``` +```jldoctest julia> a = destroy(20) Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: -⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢ - -julia> kron(a, a) -Quantum Object: type=Operator dims=[20, 20] size=(400, 400) ishermitian=false -400×400 SparseMatrixCSC{ComplexF64, Int64} with 361 stored entries: -⠀⠀⠘⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠦ +⎡⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⎤ +⎢⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⎥ +⎢⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⎥ +⎢⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⎥ +⎣⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⎦ + +julia> O = kron(a, a); + +julia> size(a), size(O) +((20, 20), (400, 400)) + +julia> a.dims, O.dims +([20], [20, 20]) ``` """ function LinearAlgebra.kron( diff --git a/src/qobj/operators.jl b/src/qobj/operators.jl index 9ce68001..b2036dce 100644 --- a/src/qobj/operators.jl +++ b/src/qobj/operators.jl @@ -88,7 +88,7 @@ This operator acts on a fock state as ``\hat{a} \ket{n} = \sqrt{n} \ket{n-1}``. # Examples -``` +```jldoctest julia> a = destroy(20) Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: @@ -113,7 +113,7 @@ This operator acts on a fock state as ``\hat{a}^\dagger \ket{n} = \sqrt{n+1} \ke # Examples -``` +```jldoctest julia> a_d = create(20) Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: @@ -242,14 +242,14 @@ The parameter `which` specifies which of the following operator to return. Note that if the parameter `which` is not specified, returns a set of Spin-`j` operators: ``(\hat{S}_x, \hat{S}_y, \hat{S}_z)`` # Examples -``` +```jldoctest julia> jmat(0.5, :x) Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=true 2×2 SparseMatrixCSC{ComplexF64, Int64} with 2 stored entries: ⋅ 0.5+0.0im 0.5+0.0im ⋅ -julia> jmat(0.5, :-) +julia> jmat(0.5, Val(:-)) Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=false 2×2 SparseMatrixCSC{ComplexF64, Int64} with 1 stored entry: ⋅ ⋅ diff --git a/src/qobj/quantum_object.jl b/src/qobj/quantum_object.jl index d31f95ac..46a38d7d 100644 --- a/src/qobj/quantum_object.jl +++ b/src/qobj/quantum_object.jl @@ -19,7 +19,7 @@ Julia struct representing any quantum objects. # Examples -``` +```jldoctest julia> a = destroy(20) Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: diff --git a/src/qobj/quantum_object_base.jl b/src/qobj/quantum_object_base.jl index ea4f9df2..e4cb9644 100644 --- a/src/qobj/quantum_object_base.jl +++ b/src/qobj/quantum_object_base.jl @@ -19,7 +19,7 @@ export Bra, Ket, Operator, OperatorBra, OperatorKet, SuperOperator Abstract type for all quantum objects like [`QuantumObject`](@ref) and [`QuantumObjectEvolution`](@ref). # Example -``` +```jldoctest julia> sigmax() isa AbstractQuantumObject true ``` diff --git a/src/qobj/quantum_object_evo.jl b/src/qobj/quantum_object_evo.jl index d2acb544..8abadb3b 100644 --- a/src/qobj/quantum_object_evo.jl +++ b/src/qobj/quantum_object_evo.jl @@ -17,7 +17,7 @@ where ``c_i(p, t)`` is a function that depends on the parameters `p` and time `t # Examples This operator can be initialized in the same way as the QuTiP `QobjEvo` object. For example -``` +```jldoctest qobjevo julia> a = tensor(destroy(10), qeye(2)) Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 18 stored entries: @@ -31,13 +31,13 @@ julia> coef1(p, t) = exp(-1im * t) coef1 (generic function with 1 method) julia> op = QuantumObjectEvolution(a, coef1) -Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true +Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) ``` If there are more than 2 operators, we need to put each set of operator and coefficient function into a two-element `Tuple`, and put all these `Tuple`s together in a larger `Tuple`: -``` +```jldoctest qobjevo julia> σm = tensor(qeye(10), sigmam()) Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 10 stored entries: @@ -51,12 +51,12 @@ julia> coef2(p, t) = sin(t) coef2 (generic function with 1 method) julia> op1 = QuantumObjectEvolution(((a, coef1), (σm, coef2))) -Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true +Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false (ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20)) ``` We can also concretize the operator at a specific time `t` -``` +```jldoctest qobjevo julia> op1(0.1) Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 28 stored entries: @@ -68,7 +68,7 @@ Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=fal ``` It also supports parameter-dependent time evolution -``` +```jldoctest qobjevo julia> coef1(p, t) = exp(-1im * p.ω1 * t) coef1 (generic function with 1 method) @@ -76,7 +76,7 @@ julia> coef2(p, t) = sin(p.ω2 * t) coef2 (generic function with 1 method) julia> op1 = QuantumObjectEvolution(((a, coef1), (σm, coef2))) -Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true +Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false (ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20)) julia> p = (ω1 = 1.0, ω2 = 0.5) @@ -310,7 +310,7 @@ Apply the time-dependent [`QuantumObjectEvolution`](@ref) object `A` to the inpu - `ψout::QuantumObject`: The output state. # Examples -``` +```jldoctest julia> a = destroy(20) Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: @@ -327,49 +327,15 @@ julia> coef2(p, t) = cos(t) coef2 (generic function with 1 method) julia> A = QobjEvo(((a, coef1), (a', coef2))) -Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=true +Quantum Object Evo.: type=Operator dims=[20] size=(20, 20) ishermitian=true isconstant=false (ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20)) -julia> ψ1 = fock(20, 3) -Quantum Object: type=Ket dims=[20] size=(20,) -20-element Vector{ComplexF64}: - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - 1.0 + 0.0im - 0.0 + 0.0im - ⋮ - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - -julia> ψ2 = zero_ket(20) -Quantum Object: type=Ket dims=[20] size=(20,) -20-element Vector{ComplexF64}: - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - ⋮ - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - -julia> A(ψ2, ψ1, nothing, 0.1) -20-element Vector{ComplexF64}: - 0.0 + 0.0im - 0.0 + 0.0im - 0.1729165499254989 + 0.0im - 0.0 + 0.0im - 1.9900083305560516 + 0.0im - ⋮ - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im - 0.0 + 0.0im +julia> ψ1 = fock(20, 3); + +julia> ψ2 = zero_ket(20); + +julia> A(ψ2, ψ1, nothing, 0.1) ≈ A(0.1) * ψ1 +true ``` """ function (A::QuantumObjectEvolution)( diff --git a/src/qobj/states.jl b/src/qobj/states.jl index 92c5ff20..8634c278 100644 --- a/src/qobj/states.jl +++ b/src/qobj/states.jl @@ -252,7 +252,7 @@ Here, `x = 1` (`z = 1`) means applying Pauli-``X`` ( Pauli-``Z``) unitary transf # Example -``` +```jldoctest julia> bell_state(0, 0) Quantum Object: type=Ket dims=[2, 2] size=(4,) 4-element Vector{ComplexF64}: diff --git a/src/qobj/synonyms.jl b/src/qobj/synonyms.jl index 05a3a95a..6518d00a 100644 --- a/src/qobj/synonyms.jl +++ b/src/qobj/synonyms.jl @@ -25,7 +25,7 @@ Generate [`QuantumObjectEvolution`](@ref). Note that this functions is same as `QuantumObjectEvolution(op, f; type = type)`. The `f` parameter is used to pre-apply a function to the operators before converting them to SciML operators. The `type` parameter is used to specify the type of the [`QuantumObject`](@ref), either `Operator` or `SuperOperator`. # Examples -``` +```jldoctest julia> a = tensor(destroy(10), qeye(2)) Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 18 stored entries: @@ -36,10 +36,10 @@ Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=fal ⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⎦ julia> coef(p, t) = exp(-1im * t) -coef1 (generic function with 1 method) +coef (generic function with 1 method) julia> op = QobjEvo(a, coef) -Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true +Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) ``` """ @@ -62,7 +62,7 @@ Note that this functions is same as `QuantumObjectEvolution(op_func_list)`. If ` # Examples This operator can be initialized in the same way as the QuTiP `QobjEvo` object. For example -``` +```jldoctest qobjevo julia> a = tensor(destroy(10), qeye(2)) Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 18 stored entries: @@ -88,12 +88,12 @@ julia> coef2(p, t) = sin(t) coef2 (generic function with 1 method) julia> op1 = QobjEvo(((a, coef1), (σm, coef2))) -Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true +Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false (ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20)) ``` We can also concretize the operator at a specific time `t` -``` +```jldoctest qobjevo julia> op1(0.1) Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 28 stored entries: @@ -105,7 +105,7 @@ Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=fal ``` It also supports parameter-dependent time evolution -``` +```jldoctest qobjevo julia> coef1(p, t) = exp(-1im * p.ω1 * t) coef1 (generic function with 1 method) @@ -113,7 +113,7 @@ julia> coef2(p, t) = sin(p.ω2 * t) coef2 (generic function with 1 method) julia> op1 = QobjEvo(((a, coef1), (σm, coef2))) -Quantum Object: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true +Quantum Object Evo.: type=Operator dims=[10, 2] size=(20, 20) ishermitian=true isconstant=false (ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20) + ScalarOperator(0.0 + 0.0im) * MatrixOperator(20 × 20)) julia> p = (ω1 = 1.0, ω2 = 0.5) @@ -290,7 +290,7 @@ Note that this function is same as `kron(A, B, ...)`. # Examples -``` +```jldoctest julia> x = sigmax() Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=true 2×2 SparseMatrixCSC{ComplexF64, Int64} with 2 stored entries: @@ -299,17 +299,11 @@ Quantum Object: type=Operator dims=[2] size=(2, 2) ishermitian=true julia> x_list = fill(x, 3); -julia> tensor(x_list...) -Quantum Object: type=Operator dims=[2, 2, 2] size=(8, 8) ishermitian=true -8×8 SparseMatrixCSC{ComplexF64, Int64} with 8 stored entries: - ⋅ ⋅ ⋅ … ⋅ ⋅ 1.0+0.0im - ⋅ ⋅ ⋅ ⋅ 1.0+0.0im ⋅ - ⋅ ⋅ ⋅ 1.0+0.0im ⋅ ⋅ - ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ - ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ - ⋅ ⋅ 1.0+0.0im … ⋅ ⋅ ⋅ - ⋅ 1.0+0.0im ⋅ ⋅ ⋅ ⋅ - 1.0+0.0im ⋅ ⋅ ⋅ ⋅ ⋅ +julia> tensor(x_list...).dims +3-element SVector{3, Int64} with indices SOneTo(3): + 2 + 2 + 2 ``` """ tensor(A...) = kron(A...) @@ -323,40 +317,23 @@ Note that this function is same as `kron(A, B)`. # Examples -``` +```jldoctest julia> a = destroy(20) Quantum Object: type=Operator dims=[20] size=(20, 20) ishermitian=false 20×20 SparseMatrixCSC{ComplexF64, Int64} with 19 stored entries: -⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢ - -julia> a ⊗ a -Quantum Object: type=Operator dims=[20, 20] size=(400, 400) ishermitian=false -400×400 SparseMatrixCSC{ComplexF64, Int64} with 361 stored entries: -⠀⠀⠘⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀⠀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢦⡀⠀ -⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⠦ +⎡⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⎤ +⎢⠀⠀⠈⠢⡀⠀⠀⠀⠀⠀⎥ +⎢⠀⠀⠀⠀⠈⠢⡀⠀⠀⠀⎥ +⎢⠀⠀⠀⠀⠀⠀⠈⠢⡀⠀⎥ +⎣⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⎦ + +julia> O = a ⊗ a; + +julia> size(a), size(O) +((20, 20), (400, 400)) + +julia> a.dims, O.dims +([20], [20, 20]) ``` """ ⊗(A::QuantumObject, B::QuantumObject) = kron(A, B) diff --git a/src/utilities.jl b/src/utilities.jl index 150751e6..5a426bd1 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -67,7 +67,7 @@ The current stored constants are: # Examples -``` +```jldoctest julia> PhysicalConstants.ħ 1.0545718176461565e-34 ``` @@ -111,15 +111,15 @@ Note that we use the values stored in [`PhysicalConstants`](@ref) to do the conv # Examples -``` +```jldoctest julia> convert_unit(1, :eV, :J) 1.602176634e-19 julia> convert_unit(1, :GHz, :J) 6.62607015e-25 -julia> convert_unit(1, :meV, :mK) -11604.518121550082 +julia> round(convert_unit(1, :meV, :mK), digits=4) +11604.5181 ``` """ function convert_unit(value::T, unit1::Symbol, unit2::Symbol) where {T<:Real} diff --git a/src/wigner.jl b/src/wigner.jl index c64bf818..4c8ee7fa 100644 --- a/src/wigner.jl +++ b/src/wigner.jl @@ -35,7 +35,7 @@ The `method` parameter can be either `WignerLaguerre()` or `WignerClenshaw()`. T - `W::Matrix`: The Wigner function of the state at the points `xvec + 1im * yvec` in phase space. # Example -``` +```jldoctest wigner julia> ψ = fock(10, 0) + fock(10, 1) |> normalize Quantum Object: type=Ket dims=[10] size=(10,) 10-element Vector{ComplexF64}: @@ -53,37 +53,16 @@ Quantum Object: type=Ket dims=[10] size=(10,) julia> xvec = range(-5, 5, 200) -5.0:0.05025125628140704:5.0 -julia> wig = wigner(ψ, xvec, xvec) -200×200 Matrix{Float64}: - 2.63558e-21 4.30187e-21 6.98638e-21 1.12892e-20 1.81505e-20 … 1.50062e-20 9.28736e-21 5.71895e-21 3.50382e-21 - 4.29467e-21 7.00905e-21 1.13816e-20 1.83891e-20 2.9562e-20 2.45173e-20 1.51752e-20 9.3454e-21 5.72614e-21 - 6.96278e-21 1.13621e-20 1.8448e-20 2.98026e-20 4.79043e-20 3.98553e-20 2.46711e-20 1.51947e-20 9.31096e-21 - 1.12314e-20 1.83256e-20 2.97505e-20 4.80558e-20 7.72344e-20 6.4463e-20 3.99074e-20 2.45808e-20 1.50639e-20 - 1.80254e-20 2.94073e-20 4.77351e-20 7.70963e-20 1.23892e-19 1.0374e-19 6.42289e-20 3.95652e-20 2.42491e-20 - ⋮ ⋱ - 1.80254e-20 2.94073e-20 4.77351e-20 7.70963e-20 1.23892e-19 … 1.0374e-19 6.42289e-20 3.95652e-20 2.42491e-20 - 1.12314e-20 1.83256e-20 2.97505e-20 4.80558e-20 7.72344e-20 6.4463e-20 3.99074e-20 2.45808e-20 1.50639e-20 - 6.96278e-21 1.13621e-20 1.8448e-20 2.98026e-20 4.79043e-20 3.98553e-20 2.46711e-20 1.51947e-20 9.31096e-21 - 4.29467e-21 7.00905e-21 1.13816e-20 1.83891e-20 2.9562e-20 2.45173e-20 1.51752e-20 9.3454e-21 5.72614e-21 - 2.63558e-21 4.30187e-21 6.98638e-21 1.12892e-20 1.81505e-20 1.50062e-20 9.28736e-21 5.71895e-21 3.50382e-21 +julia> wig = wigner(ψ, xvec, xvec); ``` or taking advantage of the parallel computation of the `WignerLaguerre` method -``` -julia> wig = wigner(ρ, xvec, xvec, method=WignerLaguerre(parallel=true)) -200×200 Matrix{Float64}: - 2.63558e-21 4.30187e-21 6.98638e-21 1.12892e-20 1.81505e-20 … 1.50062e-20 9.28736e-21 5.71895e-21 3.50382e-21 - 4.29467e-21 7.00905e-21 1.13816e-20 1.83891e-20 2.9562e-20 2.45173e-20 1.51752e-20 9.3454e-21 5.72614e-21 - 6.96278e-21 1.13621e-20 1.8448e-20 2.98026e-20 4.79043e-20 3.98553e-20 2.46711e-20 1.51947e-20 9.31096e-21 - 1.12314e-20 1.83256e-20 2.97505e-20 4.80558e-20 7.72344e-20 6.4463e-20 3.99074e-20 2.45808e-20 1.50639e-20 - 1.80254e-20 2.94073e-20 4.77351e-20 7.70963e-20 1.23892e-19 1.0374e-19 6.42289e-20 3.95652e-20 2.42491e-20 - ⋮ ⋱ - 1.80254e-20 2.94073e-20 4.77351e-20 7.70963e-20 1.23892e-19 … 1.0374e-19 6.42289e-20 3.95652e-20 2.42491e-20 - 1.12314e-20 1.83256e-20 2.97505e-20 4.80558e-20 7.72344e-20 6.4463e-20 3.99074e-20 2.45808e-20 1.50639e-20 - 6.96278e-21 1.13621e-20 1.8448e-20 2.98026e-20 4.79043e-20 3.98553e-20 2.46711e-20 1.51947e-20 9.31096e-21 - 4.29467e-21 7.00905e-21 1.13816e-20 1.83891e-20 2.9562e-20 2.45173e-20 1.51752e-20 9.3454e-21 5.72614e-21 - 2.63558e-21 4.30187e-21 6.98638e-21 1.12892e-20 1.81505e-20 1.50062e-20 9.28736e-21 5.71895e-21 3.50382e-21 +```jldoctest wigner +julia> ρ = ket2dm(ψ) |> dense_to_sparse; + +julia> wig = wigner(ρ, xvec, xvec, method=WignerLaguerre(parallel=true)); + ``` """ function wigner( From c21855b461945f31b4463863c2d794f6a2899a90 Mon Sep 17 00:00:00 2001 From: Alberto Mercurio Date: Mon, 11 Nov 2024 09:04:08 +0100 Subject: [PATCH 2/2] Fix round error --- src/negativity.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/negativity.jl b/src/negativity.jl index 416020c8..c5984487 100644 --- a/src/negativity.jl +++ b/src/negativity.jl @@ -34,8 +34,8 @@ Quantum Object: type=Operator dims=[2, 2] size=(4, 4) ishermitian=true 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im 0.5+0.0im -julia> negativity(ρ, 2) |> round -0.0 +julia> round(negativity(ρ, 2), digits=2) +0.5 ``` """ function negativity(ρ::QuantumObject, subsys::Int; logarithmic::Bool = false)