diff --git a/src/QuantumClifford.jl b/src/QuantumClifford.jl index ffe679a0d..6f22a6fff 100644 --- a/src/QuantumClifford.jl +++ b/src/QuantumClifford.jl @@ -989,6 +989,16 @@ function _apply!(stab::AbstractStabilizer, p::PauliOperator, indices; phases::Va stab end +############################## +# Conversion and promotion +############################## + +Base.promote_rule(::Type{<:Destabilizer{T}} , ::Type{<:MixedDestabilizer{T}}) where {T<:Tableau} = MixedDestabilizer{T} +Base.promote_rule(::Type{<:MixedStabilizer{T}}, ::Type{<:MixedDestabilizer{T}}) where {T<:Tableau} = MixedDestabilizer{T} +Base.promote_rule(::Type{<:Stabilizer{T}} , ::Type{<:S} ) where {T<:Tableau, S<:Union{MixedStabilizer{T}, Destabilizer{T}, MixedDestabilizer{T}}} = S + +Base.convert(::Type{<:MixedDestabilizer{T}}, x::Union{Destabilizer{T}, MixedStabilizer{T}, Stabilizer{T}}) where {T <: Tableau} = MixedDestabilizer(x) + ############################## # Helpers for binary codes ############################## diff --git a/src/linalg.jl b/src/linalg.jl index 16b4eaf52..b95fba888 100644 --- a/src/linalg.jl +++ b/src/linalg.jl @@ -161,8 +161,10 @@ julia> tensor(s, s) See also [`tensor_pow`](@ref).""" function tensor end -function tensor(ops::AbstractStabilizer...) # TODO optimize this by doing conversion to common type to enable preallocation - foldl(⊗, ops[2:end], init=ops[1]) +function tensor(ops::AbstractStabilizer...) # TODO optimize by pre-allocating one large tableau instead of the current quadratic fold + ct = promote_type(map(typeof, ops)...) + conv_ops = map(x -> convert(ct, x), ops) + return foldl(⊗, conv_ops) end """Repeated tensor product of an operators or a tableau. diff --git a/test/test_stabs.jl b/test/test_stabs.jl index 63a5c562e..d415621ea 100644 --- a/test/test_stabs.jl +++ b/test/test_stabs.jl @@ -55,6 +55,12 @@ stabs = [s[1:i] for s in [random_stabilizer(n) for n in [32,16,16,64,63,65,129,128,127]] for i in rand(1:10)]; mdstabs = MixedDestabilizer.(stabs); @test canonicalize!(⊗(stabs...)) == canonicalize!(stabilizerview(⊗(mdstabs...))) + md = MixedDestabilizer(random_destabilizer(n)) + s = random_stabilizer(n) + mds = md⊗s + @test mixed_destab_looks_good(mds) + estab = stabilizerview(md)⊗s + @test canonicalize!(copy(stabilizerview(mds))) == canonicalize!(estab) end end