From b59db60953d7d9aacf0f91e75ef69b9d71db11b5 Mon Sep 17 00:00:00 2001 From: Akira Kyle Date: Fri, 6 Dec 2024 17:14:38 -0700 Subject: [PATCH] Continue working towards #40 --- src/abstract_types.jl | 6 ++++-- src/bases.jl | 20 ++++++++++++++++++++ src/deprecated.jl | 36 ++++++++++++++++++++++-------------- src/expect_variance.jl | 6 ++++-- src/linalg.jl | 6 +++--- test/test_bases.jl | 2 +- 6 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/abstract_types.jl b/src/abstract_types.jl index fc4cbbd..761c42c 100644 --- a/src/abstract_types.jl +++ b/src/abstract_types.jl @@ -2,8 +2,10 @@ Abstract type for all specialized bases of a Hilbert space. The `Basis` type specifies an orthonormal basis for the Hilbert -space of the studied system. All subtypes must implement `Base.:(==)` along with -`Base.length`, which should return the total dimension of the Hilbert space. +space of the studied system. All subtypes must implement `Base.:(==)`, +and `Base.size`. `size` should return a tuple representing the total dimension +of the Hilbert space with any tensor product structure the basis has such that +`length(b::Basis) = prod(size(b))` gives the total Hilbert dimension Composite systems can be defined with help of [`CompositeBasis`](@ref). diff --git a/src/bases.jl b/src/bases.jl index 5b9c74e..a07bb69 100644 --- a/src/bases.jl +++ b/src/bases.jl @@ -8,6 +8,7 @@ Total dimension of the Hilbert space. """ Base.length(b::Basis) = prod(b.shape) +#Base.length(b::Basis) = prod(size(b)) """ GenericBasis(N) @@ -43,6 +44,7 @@ CompositeBasis(bases) = CompositeBasis([length(b) for b ∈ bases], bases) CompositeBasis(bases::Basis...) = CompositeBasis((bases...,)) CompositeBasis(bases::Vector) = CompositeBasis((bases...,)) bases(b::CompositeBasis) = b.bases +Base.size(b::CompositeBasis) = length.(b.bases) Base.:(==)(b1::T, b2::T) where T<:CompositeBasis = equal_shape(b1.shape, b2.shape) @@ -172,8 +174,26 @@ struct KetBraBasis <: Basis left::Basis right::Basis end +KetBraBasis(b::Basis) = KetBraBasis(b,b) basis_l(b::KetBraBasis) = b.left basis_r(b::KetBraBasis) = b.right +Base.:(==)(b1::KetBraBasis, b2::KetBraBasis) = (b1.left == b2.left && b1.right == b2.right) +Base.length(b::KetBraBasis) = length(b.left)*length(b.right) +Base.size(b::KetBraBasis) = (length(b.left), length(b.right)) + +struct ChoiRefSysBasis <: Basis + basis::Basis +end +Base.:(==)(b1::ChoiRefSysBasis, b2::ChoiRefSysBasis) = (b1.basis == b2.basis) +Base.length(b::ChoiRefSysBasis) = length(b.basis) +Base.size(b::ChoiRefSysBasis) = (length(b.basis),) + +struct ChoiOutSysBasis <: Basis + basis::Basis +end +Base.:(==)(b1::ChoiOutSysBasis, b2::ChoiOutSysBasis) = (b1.basis == b2.basis) +Base.length(b::ChoiOutSysBasis) = length(b.basis) +Base.size(b::ChoiOutSysBasis) = (length(b.basis),) """ PauliBasis() diff --git a/src/deprecated.jl b/src/deprecated.jl index febdddf..5fbabd9 100644 --- a/src/deprecated.jl +++ b/src/deprecated.jl @@ -11,47 +11,46 @@ function equal_bases(a, b) return true end -Base.@deprecate PauliBasis(num_qubits) NQubitBasis(num_qubits) false - function samebases(b1::Basis, b2::Basis) - Base.depwarn("`==` should be preferred over `samebases(b1::Basis, b2::Basis)`!", :samebases) + #Base.depwarn("`==` should be preferred over `samebases(b1::Basis, b2::Basis)`!", :samebases) b1==b2 end function samebases(b1::Tuple{Basis, Basis}, b2::Tuple{Basis, Basis}) - Base.depwarn("`==` should be preferred over `samebases(b1::Tuple{Basis, Basis}, b2::Tuple{Basis, Basis})`!", :samebases) + #Base.depwarn("`==` should be preferred over `samebases(b1::Tuple{Basis, Basis}, b2::Tuple{Basis, Basis})`!", :samebases) b1==b2 # for checking superoperators end function samebases(a::AbstractOperator) - Base.depwarn("`issquare` should be preferred over `samebases(a::AbstractOperator)`!", :check_samebases) + #Base.depwarn("`issquare` should be preferred over `samebases(a::AbstractOperator)`!", :check_samebases) samebases(a.basis_l, a.basis_r)::Bool # FIXME issue #12 end function samebases(a::AbstractOperator, b::AbstractOperator) - Base.depwarn("`addible` should be preferred over `samebases(a::AbstractOperator, b::AbstractOperator)`!", :check_samebases) + #Base.depwarn("`addible` should be preferred over `samebases(a::AbstractOperator, b::AbstractOperator)`!", :check_samebases) samebases(a.basis_l, b.basis_l)::Bool && samebases(a.basis_r, b.basis_r)::Bool # FIXME issue #12 end function check_samebases(b1, b2) - Base.depwarn("Depending on context, `check__multiplicable`, `check_addible`, or `check_issquare` should be preferred over `check_samebases`!", :check_samebases) + #Base.depwarn("Depending on context, `check__multiplicable`, `check_addible`, or `check_issquare` should be preferred over `check_samebases`!", :check_samebases) if BASES_CHECK[] && !samebases(b1, b2) throw(IncompatibleBases()) end end -function check_samebases(a::Union{AbstractOperator, AbstractSuperOperator}) - Base.depwarn("`check_issquare` should be preferred over `check_samebases(a::Union{AbstractOperator, AbstractSuperOperator})`!", :check_samebases) - check_samebases(a.basis_l, a.basis_r) # FIXME issue #12 -end +check_samebases(a::AbstractOperator) = check_samebases(a.basis_l, a.basis_r) # FIXME issue #12 + +""" +check_samebases(a::Union{AbstractOperator, AbstractSuperOperator}) = check_samebases(a.basis_l, a.basis_r) # FIXME issue #12 +""" function multiplicable(b1::Basis, b2::Basis) - Base.depwarn("`==` should be preferred over `multiplicable(b1::Basis, b2::Basis)`!", :multiplicable) + #Base.depwarn("`==` should be preferred over `multiplicable(b1::Basis, b2::Basis)`!", :multiplicable) b1==b2 end function multiplicable(b1::CompositeBasis, b2::CompositeBasis) - Base.depwarn("`==` should be preferred over `multiplicable(b1::CompositeBasis, b2::CompositeBasis)`!", :multiplicable) + #Base.depwarn("`==` should be preferred over `multiplicable(b1::CompositeBasis, b2::CompositeBasis)`!", :multiplicable) if !equal_shape(b1.shape,b2.shape) return false end @@ -63,4 +62,13 @@ function multiplicable(b1::CompositeBasis, b2::CompositeBasis) return true end -Base.@deprecate @samebases(ex) @compatiblebases(ex) false +macro samebases(ex) + return quote + BASES_CHECK.x = false + local val = $(esc(ex)) + BASES_CHECK.x = true + val + end +end + +#Base.@deprecate @samebases(ex) @compatiblebases(ex) false diff --git a/src/expect_variance.jl b/src/expect_variance.jl index 58a3343..678fb5f 100644 --- a/src/expect_variance.jl +++ b/src/expect_variance.jl @@ -23,13 +23,15 @@ If an `index` is given, it assumes that `op` is defined in the subsystem specifi variance(indices, op::AbstractOperator, state::AbstractOperator) = variance(op, ptrace(state, complement(nsubsystems(state), indices))) -variance(index::Integer, op::AbstractOperator{B,B}, state::AbstractOperator{BC,BC}) where {B,BC<:CompositeBasis} = variance([index], op, state) +variance(index::Integer, op::AbstractOperator, state::AbstractOperator) = variance([index], op, state) variance(op::AbstractOperator, states::Vector) = [variance(op, state) for state=states] variance(indices, op::AbstractOperator, states::Vector) = [variance(indices, op, state) for state=states] function variance(op::AbstractOperator, state::AbstractOperator) - check_multiplicable(op); check_multiplicable(state); check_multiplicable(op,state) + check_multiplicable(op,op) + check_multiplicable(state,state) + check_multiplicable(op,state) @compatiblebases expect(op*op, state) - expect(op, state)^2 end diff --git a/src/linalg.jl b/src/linalg.jl index a8db3a3..0fd8a26 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -43,9 +43,9 @@ multiplicable(a::AbstractOperator, b::AbstractKet) = (basis_r(a) == basis(b)) multiplicable(a::AbstractBra, b::AbstractOperator) = (basis(a) == basis_l(b)) multiplicable(a::AbstractOperator, b::AbstractOperator) = (basis_r(a) == basis_l(b)) -basis(a::StateVector) = throw(ArgumentError("basis() is not defined for this type of state vector: $(typeof(op)).")) -basis_l(a::AbstractOperator) = throw(ArgumentError("basis_l() is not defined for this type of operator: $(typeof(op)).")) -basis_r(a::AbstractOperator) = throw(ArgumentError("basis_r() is not defined for this type of operator: $(typeof(op)).")) +basis(a::StateVector) = throw(ArgumentError("basis() is not defined for this type of state vector: $(typeof(a)).")) +basis_l(a::AbstractOperator) = throw(ArgumentError("basis_l() is not defined for this type of operator: $(typeof(a)).")) +basis_r(a::AbstractOperator) = throw(ArgumentError("basis_r() is not defined for this type of operator: $(typeof(a)).")) basis(a::AbstractOperator) = (basis_l(a) == basis_r(a); basis_l(a)) ## diff --git a/test/test_bases.jl b/test/test_bases.jl index f6a98c9..cce4cd2 100644 --- a/test/test_bases.jl +++ b/test/test_bases.jl @@ -49,7 +49,7 @@ comp1 = tensor(b1, b2, b3) comp2 = tensor(b2, b1, b3) @test permutesystems(comp1, [2,1,3]) == comp2 -@test [b1, b2] !== [b1, b3] +@test [b1, b2] != [b1, b3] @test !multiplicable(comp1, b1 ⊗ b2 ⊗ NLevelBasis(prod(b3.shape))) end # testset