From 1fb178385c2a343d3cf7148505c27bd88f7990c3 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Tue, 23 Jul 2024 13:07:30 -0400 Subject: [PATCH] fix for wrong SIMD mul_left! #320 (#322) --- CHANGELOG.md | 3 +++ Project.toml | 2 +- src/mul_leftright.jl | 2 +- test/test_mul_leftright.jl | 17 ++++++++++++++++- test/test_stabcanon.jl | 13 +++++++++++++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec4e15c24..1c8952376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ # News +## v0.9.7 - 2024-07-23 + +- **(fix `#320`)** Fix a serious correctness bug in the SIMD implementation of Pauli string multiplication (affects the correctness of canonicalization and traceout for tableaux bigger than ~500 qubits; does not affect symbolic gates or Pauli frame simulations of any scale) ## v0.9.6 - 2024-07-12 - `inv` implementation for single-qubit "symbolic" Clifford operators (subtypes of `AbstractSingleQubitOperator`). diff --git a/Project.toml b/Project.toml index a2ca448b8..196ddf832 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuantumClifford" uuid = "0525e862-1e90-11e9-3e4d-1b39d7109de1" authors = ["Stefan Krastanov and QuantumSavory community members"] -version = "0.9.6" +version = "0.9.7" [deps] Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" diff --git a/src/mul_leftright.jl b/src/mul_leftright.jl index 43a3731cd..122fb1e61 100644 --- a/src/mul_leftright.jl +++ b/src/mul_leftright.jl @@ -89,7 +89,7 @@ function mul_ordered!(r::AbstractVector{T}, l::AbstractVector{T}; phases::Val{B} r[i+len+lane] = newz1 = z1 ⊻ z2 x1z2 = x1 & z2 anti_comm = (x2 & z1) ⊻ x1z2 - cnt2 ⊻= (newx1 ⊻ newz1 ⊻ x1z2) & anti_comm + cnt2 ⊻= (cnt1 ⊻ newx1 ⊻ newz1 ⊻ x1z2) & anti_comm cnt1 ⊻= anti_comm end for i in 1:length(cnt1) diff --git a/test/test_mul_leftright.jl b/test/test_mul_leftright.jl index ecf2b36eb..1d7c14e45 100644 --- a/test/test_mul_leftright.jl +++ b/test/test_mul_leftright.jl @@ -5,7 +5,7 @@ using Test test_sizes = [1,2,10,63,64,65,127,128,129] # Including sizes that would test off-by-one errors in the bit encoding. -@testset "Inner product between stabilizer states" begin +@testset "Pauli string multiplication" begin for n in test_sizes for _ in 1:20 p1 = random_pauli(n) @@ -22,3 +22,18 @@ test_sizes = [1,2,10,63,64,65,127,128,129] # Including sizes that would test off end end end + +# test for #320 +@testset "verify SIMD implementation" begin + for i in 1:10, + n in 1:30, + T in [UInt8, UInt16, UInt32, UInt64] + a = rand(T, n) + b = rand(T, n) + c1,c2 = QuantumClifford.mul_ordered!(copy(a),copy(b)) + n1,n2 = QuantumClifford._mul_ordered_nonvec!(copy(a),copy(b)) + np = ((n1 ⊻ (n2<<1))&0x3) + cp = ((c1 ⊻ (c2<<1))&0x3) + @test np==cp + end +end diff --git a/test/test_stabcanon.jl b/test/test_stabcanon.jl index 13442e4eb..5c113c69b 100644 --- a/test/test_stabcanon.jl +++ b/test/test_stabcanon.jl @@ -74,3 +74,16 @@ test_sizes = [1,2,10,63,64,65,127,128,129] # Including sizes that would test off end end end + +@testset "canonicalization invariants" begin + s = random_stabilizer(40,100) + ss = tensor_pow(s,20) + sa1 = canonicalize!(canonicalize_rref!(copy(ss))[1]) + sa2 = canonicalize!(copy(ss)) + @test sa1 == sa2 + ms = MixedDestabilizer(s) + mss = tensor_pow(ms, 20) + msa1 = canonicalize!(canonicalize_rref!(copy(mss))[1]) + msa2 = canonicalize!(copy(mss)) + @test stabilizerview(msa1) == stabilizerview(msa2) == sa1 +end