From ffe969afa75d874d71fb8a9f3819fdded1d0f3f6 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Thu, 24 Mar 2022 18:27:01 -0400 Subject: [PATCH] Val{Bool} keywords for `generate!` --- CHANGELOG.md | 5 +++-- src/project_trace_reset.jl | 19 ++++++++++++------- test/test_allocations.jl | 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e852ce0c..7179c9c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,14 @@ - Implement `trusted_rank` that returns `rank` for states that support it and `length` for others (e.g. `Stabilizer`). - Implement `length` for `[Mixed]Destabilizer`. -- Clean up code repetition between `project!` and `projectX/Y/Z!`. +- Clean up code repetition between `project!` and `projectX/Y/Z!`. Issue `#40` - More conversion constructors between different tableau types. - Implement pre-compilation examples (again) for julia 1.9+. +- `generate!` does not needlessly allocate anymore, helping `project!` on `Stabilizer`. Issue `#39` ## v0.4.2 -- `project!` does not needlessly allocate anymore on `MixedDestabilizer`. PR `#41` +- `project!` does not needlessly allocate anymore on `MixedDestabilizer`. Issue `#39`, PR `#41` ## v0.4.1 diff --git a/src/project_trace_reset.jl b/src/project_trace_reset.jl index 75a69e7b9..1582ccb6f 100644 --- a/src/project_trace_reset.jl +++ b/src/project_trace_reset.jl @@ -33,8 +33,13 @@ julia> generate!(P"XII",canonicalize!(S"XII")) === nothing false ``` """ -function generate!(pauli::PauliOperator{Tz,Tv}, stabilizer::Stabilizer{Tzv,Tm}; phases::Bool=true, saveindices::Bool=true) where {Tz<:AbstractArray{UInt8,0}, Tzv<:AbstractVector{UInt8}, Tme<:Unsigned, Tv<:AbstractVector{Tme}, Tm<:AbstractMatrix{Tme}} # TODO there is stuff that can be abstracted away here and in canonicalize! +function generate!(pauli::PauliOperator, stabilizer::Stabilizer; phases::Bool=true, saveindices::Bool=true) _phases = Val(phases) + _saveindices = Val(saveindices) + _generate!(pauli, stabilizer; phases=_phases, saveindices=_saveindices) +end + +function _generate!(pauli::PauliOperator{Tz,Tv}, stabilizer::Stabilizer{Tzv,Tm}; phases::Val{PHASES}=Val(true), saveindices::Val{SAVEIDX}=Val(true)) where {Tz<:AbstractArray{UInt8,0}, Tzv<:AbstractVector{UInt8}, Tme<:Unsigned, Tv<:AbstractVector{Tme}, Tm<:AbstractMatrix{Tme}, PHASES, SAVEIDX} # TODO there is stuff that can be abstracted away here and in canonicalize! xzs = stabilizer.xzs xs = @view xzs[1:end÷2,:] zs = @view xzs[end÷2+1:end,:] @@ -54,8 +59,8 @@ function generate!(pauli::PauliOperator{Tz,Tv}, stabilizer::Stabilizer{Tzv,Tm}; else used += candidate end - mul_left!(pauli, stabilizer, used, phases=_phases) - saveindices && push!(used_indices, used) + mul_left!(pauli, stabilizer, used, phases=phases) + SAVEIDX && push!(used_indices, used) end # remove Zs while (i=unsafe_bitfindnext_(pz,1)) !== nothing @@ -68,11 +73,11 @@ function generate!(pauli::PauliOperator{Tz,Tv}, stabilizer::Stabilizer{Tzv,Tm}; else used += candidate end - mul_left!(pauli, stabilizer, used, phases=_phases) - saveindices && push!(used_indices, used) + mul_left!(pauli, stabilizer, used, phases=phases) + SAVEIDX && push!(used_indices, used) end all(iszero, pauli.xz) || return nothing # Need to check due to cases like generate!(P"_Z", S"XZ") that bypass the X checks # TODO do this better, without this extra loop through p.xz - if saveindices + if SAVEIDX return pauli, used_indices else return pauli @@ -282,7 +287,7 @@ function _project!(stabilizer::Stabilizer,pauli::PauliOperator;keep_result::Bool if anticommutes == 0 if keep_result _,_,r = canonicalize!(stabilizer; phases=B, ranks=true) # O(n^3) - gen = generate!(copy(pauli), stabilizer, phases=B) # O(n^2) + gen = _generate!(copy(pauli), stabilizer, phases=phases) # O(n^2) if isnothing(gen) result = nothing anticommutes = r+1 diff --git a/test/test_allocations.jl b/test/test_allocations.jl index 5ec8ef662..600e77de0 100644 --- a/test/test_allocations.jl +++ b/test/test_allocations.jl @@ -51,8 +51,8 @@ function test_allocations() f3() f4() = project!(md,p) f4() - @test_broken allocated(f1) < 300 - @test_broken allocated(f2) < 300 + @test allocated(f1) < 1600 + @test allocated(f2) < 1500 @test allocated(f3) < 400 @test allocated(f4) < 450 for p! in [projectX!, projectY!, projectZ!]