From 1d5a83fa935f662185abf297cb59308b27a2a37a Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 12:22:22 +0500 Subject: [PATCH 01/15] Adding inv method for singlequbitgate with testing --- CHANGELOG.md | 4 ++++ src/QuantumClifford.jl | 1 + src/symbolic_cliffords.jl | 31 +++++++++++++++++++++++++++++++ test/test_symcliff.jl | 31 +++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 18c7f5a8b..549c0d6ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ # News +## v0.9.6 - 2024-07-12 + +- `inv` implementation for all subtypes of `AbstractCliffordOperator` + ## v0.9.5 - 2024-07-04 - Implementation of random all-to-all and brickwork Clifford circuits and corresponding ECC codes. diff --git a/src/QuantumClifford.jl b/src/QuantumClifford.jl index 44fb23312..de89d7a27 100644 --- a/src/QuantumClifford.jl +++ b/src/QuantumClifford.jl @@ -8,6 +8,7 @@ module QuantumClifford # TODO Significant performance improvements: many operations do not need phase=true if the Pauli operations commute import LinearAlgebra +import Base: inv using LinearAlgebra: inv, mul!, rank, Adjoint, dot import DataStructures using DataStructures: DefaultDict, Accumulator diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index b143589b3..31e06d3e2 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -227,6 +227,37 @@ function random_clifford1(rng::AbstractRNG, qubit) end random_clifford1(qubit) = random_clifford1(GLOBAL_RNG, qubit) + +inv(h::sHadamard) = sHadamard(h.q) +inv(p::sPhase) = sInvPhase(p.q) +inv(p::sInvPhase) = sPhase(p.q) +inv(p::sId1) = sId1(p.q) +inv(p::sX) = sX(p.q) +inv(p::sY) = sY(p.q) +inv(p::sZ) = sZ(p.q) + +function inv(op::SingleQubitOperator) + if !op.xx && op.xz && op.zx && !op.zz && !op.px && !op.pz + return sHadamard(op.q) + elseif op.xx && op.xz && !op.zx && op.zz && !op.px && !op.pz + return sInvPhase(op.q) + elseif op.xx && op.xz && !op.zx && op.zz && op.px && !op.pz + return sPhase(op.q) + elseif op.xx && !op.xz && !op.zx && op.zz && !op.px && !op.pz + return sId1(op.q) + elseif op.xx && !op.xz && !op.zx && op.zz && !op.px && op.pz + return sX(op.q) + elseif op.xx && !op.xz && !op.zx && op.zz && op.px && op.pz + return sY(op.q) + elseif op.xx && !op.xz && !op.zx && op.zz && op.px && !op.pz + return sZ(op.q) + else + throw(ArgumentError("Unknown SingleQubitOperator: cannot determine inverse")) + end +end + +inv(op::AbstractSingleQubitOperator) = inv(SingleQubitOperator(op)) + ############################## # Two-qubit gates ############################## diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 9cfddb976..ed1a8d481 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -66,3 +66,34 @@ end @test op1 == op2 end end + +@testset "SingleQubitOperator Inv methods" begin + inv_op = inv(SingleQubitOperator(sHadamard(1))) + expected_inv_op = sHadamard(1) + @test inv_op == expected_inv_op + @test inv_op == inv(sHadamard(1)) + inv_op = inv(SingleQubitOperator(sPhase(1))) + expected_inv_op = sInvPhase(1) + @test inv_op == expected_inv_op + @test inv_op == inv(sPhase(1)) + inv_op = inv(SingleQubitOperator(sInvPhase(1))) + expected_inv_op = sPhase(1) + @test inv_op == expected_inv_op + @test inv_op == inv(sInvPhase(1)) + inv_op = inv(SingleQubitOperator(sX(1))) + expected_inv_op = sX(1) + @test inv_op == expected_inv_op + @test inv_op == inv(sX(1)) + inv_op = inv(SingleQubitOperator(sY(1))) + expected_inv_op = sY(1) + @test inv_op == expected_inv_op + @test inv_op == inv(sY(1)) + inv_op = inv(SingleQubitOperator(sZ(1))) + expected_inv_op = sZ(1) + @test inv_op == expected_inv_op + @test inv_op == inv(sZ(1)) + inv_op = inv(SingleQubitOperator(sId1(1))) + expected_inv_op = sId1(1) + @test inv_op == expected_inv_op + @test inv_op == inv(sId1(1)) +end From a2ad7b2e02c92c1a268c896cfcd5385929131c92 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 12:31:47 +0500 Subject: [PATCH 02/15] fix the import of Base.inv --- src/symbolic_cliffords.jl | 2 +- test/test_symcliff.jl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index 31e06d3e2..aae43cd4f 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -1,4 +1,5 @@ using Random: AbstractRNG, GLOBAL_RNG +import Base: inv """Supertype of all symbolic operators. Subtype of `AbstractCliffordOperator`""" abstract type AbstractSymbolicOperator <: AbstractCliffordOperator end @@ -227,7 +228,6 @@ function random_clifford1(rng::AbstractRNG, qubit) end random_clifford1(qubit) = random_clifford1(GLOBAL_RNG, qubit) - inv(h::sHadamard) = sHadamard(h.q) inv(p::sPhase) = sInvPhase(p.q) inv(p::sInvPhase) = sPhase(p.q) diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index ed1a8d481..de7a1cc7b 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -1,6 +1,6 @@ using Random using QuantumClifford - +import Base: inv using QuantumClifford: stab_looks_good, destab_looks_good, mixed_stab_looks_good, mixed_destab_looks_good using QuantumClifford: apply_single_x!, apply_single_y!, apply_single_z! using InteractiveUtils From b1170d084984981f51a9d31728cec454c167a3cc Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 13:23:43 +0500 Subject: [PATCH 03/15] Renaming CHANGELOG, improving tests quality --- CHANGELOG.md | 2 +- test/test_symcliff.jl | 38 ++++++++++---------------------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 549c0d6ba..b51a72eb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ## v0.9.6 - 2024-07-12 -- `inv` implementation for all subtypes of `AbstractCliffordOperator` +- `inv` implementation for `SingleQubitOperator`. ## v0.9.5 - 2024-07-04 diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index de7a1cc7b..d576c01f3 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -1,6 +1,7 @@ using Random using QuantumClifford import Base: inv +using QuantumClifford: CliffordOperator using QuantumClifford: stab_looks_good, destab_looks_good, mixed_stab_looks_good, mixed_destab_looks_good using QuantumClifford: apply_single_x!, apply_single_y!, apply_single_z! using InteractiveUtils @@ -68,32 +69,13 @@ end end @testset "SingleQubitOperator Inv methods" begin - inv_op = inv(SingleQubitOperator(sHadamard(1))) - expected_inv_op = sHadamard(1) - @test inv_op == expected_inv_op - @test inv_op == inv(sHadamard(1)) - inv_op = inv(SingleQubitOperator(sPhase(1))) - expected_inv_op = sInvPhase(1) - @test inv_op == expected_inv_op - @test inv_op == inv(sPhase(1)) - inv_op = inv(SingleQubitOperator(sInvPhase(1))) - expected_inv_op = sPhase(1) - @test inv_op == expected_inv_op - @test inv_op == inv(sInvPhase(1)) - inv_op = inv(SingleQubitOperator(sX(1))) - expected_inv_op = sX(1) - @test inv_op == expected_inv_op - @test inv_op == inv(sX(1)) - inv_op = inv(SingleQubitOperator(sY(1))) - expected_inv_op = sY(1) - @test inv_op == expected_inv_op - @test inv_op == inv(sY(1)) - inv_op = inv(SingleQubitOperator(sZ(1))) - expected_inv_op = sZ(1) - @test inv_op == expected_inv_op - @test inv_op == inv(sZ(1)) - inv_op = inv(SingleQubitOperator(sId1(1))) - expected_inv_op = sId1(1) - @test inv_op == expected_inv_op - @test inv_op == inv(sId1(1)) + @test CliffordOperator(inv(SingleQubitOperator(sHadamard(1))), 1) == inv(CliffordOperator(sHadamard)) + @test CliffordOperator(inv(SingleQubitOperator(sX(1))), 1) == inv(CliffordOperator(sX)) + @test CliffordOperator(inv(SingleQubitOperator(sY(1))), 1) == inv(CliffordOperator(sY)) + @test CliffordOperator(inv(SingleQubitOperator(sZ(1))), 1) == inv(CliffordOperator(sZ)) + @test CliffordOperator(inv(SingleQubitOperator(sId1(1))), 1) == inv(CliffordOperator(sId1)) + @test CliffordOperator(inv(SingleQubitOperator(sPhase(1))), 1) == inv(CliffordOperator(sPhase(1),1)) + @test CliffordOperator(inv(SingleQubitOperator(sPhase(1))), 1) == CliffordOperator(sPhase(1),1) |> inv + @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == inv(CliffordOperator(sInvPhase(1),1)) + @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == CliffordOperator(sInvPhase(1),1) |> inv end From d1d31c83eac00b93beb532f129c2583c41618f15 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 14:05:22 +0500 Subject: [PATCH 04/15] Improve codecoverage from 62.50% to > 82% --- CHANGELOG.md | 2 +- test/test_symcliff.jl | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b51a72eb1..f6b787a92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ## v0.9.6 - 2024-07-12 -- `inv` implementation for `SingleQubitOperator`. +- `inv` implementation for the `SingleQubitOperator`. ## v0.9.5 - 2024-07-04 diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index d576c01f3..03a02fdea 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -68,7 +68,7 @@ end end end -@testset "SingleQubitOperator Inv methods" begin +@testset "SingleQubitOperator inv methods" begin @test CliffordOperator(inv(SingleQubitOperator(sHadamard(1))), 1) == inv(CliffordOperator(sHadamard)) @test CliffordOperator(inv(SingleQubitOperator(sX(1))), 1) == inv(CliffordOperator(sX)) @test CliffordOperator(inv(SingleQubitOperator(sY(1))), 1) == inv(CliffordOperator(sY)) @@ -78,4 +78,13 @@ end @test CliffordOperator(inv(SingleQubitOperator(sPhase(1))), 1) == CliffordOperator(sPhase(1),1) |> inv @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == inv(CliffordOperator(sInvPhase(1),1)) @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == CliffordOperator(sInvPhase(1),1) |> inv + @test CliffordOperator(inv(sHadamard(1)), 1) == inv(CliffordOperator(sHadamard)) + @test CliffordOperator(inv(sX(1)), 1) == inv(CliffordOperator(sX)) + @test CliffordOperator(inv(sY(1)), 1) == inv(CliffordOperator(sY)) + @test CliffordOperator(inv(sZ(1)), 1) == inv(CliffordOperator(sZ)) + @test CliffordOperator(inv(sId1(1)), 1) == inv(CliffordOperator(sId1)) + @test CliffordOperator(inv(sPhase(1)), 1) == inv(CliffordOperator(sPhase(1),1)) + @test CliffordOperator(inv(sPhase(1)), 1) == CliffordOperator(sPhase(1),1) |> inv + @test CliffordOperator(inv(sInvPhase(1)), 1) == inv(CliffordOperator(sInvPhase(1),1)) + @test CliffordOperator(inv(sInvPhase(1)), 1) == CliffordOperator(sInvPhase(1),1) |> inv end From 18b3f179e825999cab47f8854899bcbd89ae6b57 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 14:10:40 +0500 Subject: [PATCH 05/15] Minor Formatting --- test/test_symcliff.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 03a02fdea..233e773ba 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -69,20 +69,20 @@ end end @testset "SingleQubitOperator inv methods" begin - @test CliffordOperator(inv(SingleQubitOperator(sHadamard(1))), 1) == inv(CliffordOperator(sHadamard)) - @test CliffordOperator(inv(SingleQubitOperator(sX(1))), 1) == inv(CliffordOperator(sX)) - @test CliffordOperator(inv(SingleQubitOperator(sY(1))), 1) == inv(CliffordOperator(sY)) - @test CliffordOperator(inv(SingleQubitOperator(sZ(1))), 1) == inv(CliffordOperator(sZ)) - @test CliffordOperator(inv(SingleQubitOperator(sId1(1))), 1) == inv(CliffordOperator(sId1)) + @test CliffordOperator(inv(SingleQubitOperator(sHadamard(1))), 1) == inv(CliffordOperator(sHadamard)) + @test CliffordOperator(inv(SingleQubitOperator(sX(1))), 1) == inv(CliffordOperator(sX)) + @test CliffordOperator(inv(SingleQubitOperator(sY(1))), 1) == inv(CliffordOperator(sY)) + @test CliffordOperator(inv(SingleQubitOperator(sZ(1))), 1) == inv(CliffordOperator(sZ)) + @test CliffordOperator(inv(SingleQubitOperator(sId1(1))), 1) == inv(CliffordOperator(sId1)) @test CliffordOperator(inv(SingleQubitOperator(sPhase(1))), 1) == inv(CliffordOperator(sPhase(1),1)) @test CliffordOperator(inv(SingleQubitOperator(sPhase(1))), 1) == CliffordOperator(sPhase(1),1) |> inv @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == inv(CliffordOperator(sInvPhase(1),1)) @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == CliffordOperator(sInvPhase(1),1) |> inv - @test CliffordOperator(inv(sHadamard(1)), 1) == inv(CliffordOperator(sHadamard)) - @test CliffordOperator(inv(sX(1)), 1) == inv(CliffordOperator(sX)) - @test CliffordOperator(inv(sY(1)), 1) == inv(CliffordOperator(sY)) - @test CliffordOperator(inv(sZ(1)), 1) == inv(CliffordOperator(sZ)) - @test CliffordOperator(inv(sId1(1)), 1) == inv(CliffordOperator(sId1)) + @test CliffordOperator(inv(sHadamard(1)), 1) == inv(CliffordOperator(sHadamard)) + @test CliffordOperator(inv(sX(1)), 1) == inv(CliffordOperator(sX)) + @test CliffordOperator(inv(sY(1)), 1) == inv(CliffordOperator(sY)) + @test CliffordOperator(inv(sZ(1)), 1) == inv(CliffordOperator(sZ)) + @test CliffordOperator(inv(sId1(1)), 1) == inv(CliffordOperator(sId1)) @test CliffordOperator(inv(sPhase(1)), 1) == inv(CliffordOperator(sPhase(1),1)) @test CliffordOperator(inv(sPhase(1)), 1) == CliffordOperator(sPhase(1),1) |> inv @test CliffordOperator(inv(sInvPhase(1)), 1) == inv(CliffordOperator(sInvPhase(1),1)) From af9ef45eeb8d3c65e83aa2818e112230a1656100 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 16:05:04 +0500 Subject: [PATCH 06/15] Code review suggestions: improving function inv, and tests - random_op left to do --- src/symbolic_cliffords.jl | 26 ++++++-------------------- test/test_symcliff.jl | 22 ++++------------------ 2 files changed, 10 insertions(+), 38 deletions(-) diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index aae43cd4f..f6026ce3e 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -228,34 +228,20 @@ function random_clifford1(rng::AbstractRNG, qubit) end random_clifford1(qubit) = random_clifford1(GLOBAL_RNG, qubit) -inv(h::sHadamard) = sHadamard(h.q) -inv(p::sPhase) = sInvPhase(p.q) -inv(p::sInvPhase) = sPhase(p.q) -inv(p::sId1) = sId1(p.q) -inv(p::sX) = sX(p.q) -inv(p::sY) = sY(p.q) -inv(p::sZ) = sZ(p.q) - function inv(op::SingleQubitOperator) - if !op.xx && op.xz && op.zx && !op.zz && !op.px && !op.pz - return sHadamard(op.q) - elseif op.xx && op.xz && !op.zx && op.zz && !op.px && !op.pz + if op.xx && op.xz && !op.zx && op.zz && !op.px && !op.pz return sInvPhase(op.q) elseif op.xx && op.xz && !op.zx && op.zz && op.px && !op.pz return sPhase(op.q) - elseif op.xx && !op.xz && !op.zx && op.zz && !op.px && !op.pz - return sId1(op.q) - elseif op.xx && !op.xz && !op.zx && op.zz && !op.px && op.pz - return sX(op.q) - elseif op.xx && !op.xz && !op.zx && op.zz && op.px && op.pz - return sY(op.q) - elseif op.xx && !op.xz && !op.zx && op.zz && op.px && !op.pz - return sZ(op.q) else - throw(ArgumentError("Unknown SingleQubitOperator: cannot determine inverse")) + return SingleQubitOperator(op) end end +inv(p::sPhase) = sInvPhase(p.q) + +inv(p::sInvPhase) = sPhase(p.q) + inv(op::AbstractSingleQubitOperator) = inv(SingleQubitOperator(op)) ############################## diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 233e773ba..e924f4a64 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -69,22 +69,8 @@ end end @testset "SingleQubitOperator inv methods" begin - @test CliffordOperator(inv(SingleQubitOperator(sHadamard(1))), 1) == inv(CliffordOperator(sHadamard)) - @test CliffordOperator(inv(SingleQubitOperator(sX(1))), 1) == inv(CliffordOperator(sX)) - @test CliffordOperator(inv(SingleQubitOperator(sY(1))), 1) == inv(CliffordOperator(sY)) - @test CliffordOperator(inv(SingleQubitOperator(sZ(1))), 1) == inv(CliffordOperator(sZ)) - @test CliffordOperator(inv(SingleQubitOperator(sId1(1))), 1) == inv(CliffordOperator(sId1)) - @test CliffordOperator(inv(SingleQubitOperator(sPhase(1))), 1) == inv(CliffordOperator(sPhase(1),1)) - @test CliffordOperator(inv(SingleQubitOperator(sPhase(1))), 1) == CliffordOperator(sPhase(1),1) |> inv - @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == inv(CliffordOperator(sInvPhase(1),1)) - @test CliffordOperator(inv(SingleQubitOperator(sInvPhase(1))), 1) == CliffordOperator(sInvPhase(1),1) |> inv - @test CliffordOperator(inv(sHadamard(1)), 1) == inv(CliffordOperator(sHadamard)) - @test CliffordOperator(inv(sX(1)), 1) == inv(CliffordOperator(sX)) - @test CliffordOperator(inv(sY(1)), 1) == inv(CliffordOperator(sY)) - @test CliffordOperator(inv(sZ(1)), 1) == inv(CliffordOperator(sZ)) - @test CliffordOperator(inv(sId1(1)), 1) == inv(CliffordOperator(sId1)) - @test CliffordOperator(inv(sPhase(1)), 1) == inv(CliffordOperator(sPhase(1),1)) - @test CliffordOperator(inv(sPhase(1)), 1) == CliffordOperator(sPhase(1),1) |> inv - @test CliffordOperator(inv(sInvPhase(1)), 1) == inv(CliffordOperator(sInvPhase(1),1)) - @test CliffordOperator(inv(sInvPhase(1)), 1) == CliffordOperator(sInvPhase(1),1) |> inv + for gate_type in [sHadamard, sX, sY, sZ, sId1 , sPhase, sInvPhase] + @test CliffordOperator(inv(SingleQubitOperator(gate_type(1))), 1) == inv(CliffordOperator(gate_type)) + @test CliffordOperator(inv(gate_type(1)), 1) == inv(CliffordOperator(gate_type)) + end end From 9350945d032777c5d007f88a77bbc27c078bfb1d Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 17:54:22 +0500 Subject: [PATCH 07/15] code review suggestions --- src/symbolic_cliffords.jl | 3 ++- test/test_symcliff.jl | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index f6026ce3e..16c65870a 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -234,7 +234,8 @@ function inv(op::SingleQubitOperator) elseif op.xx && op.xz && !op.zx && op.zz && op.px && !op.pz return sPhase(op.q) else - return SingleQubitOperator(op) + c = LinearAlgebra.inv(CliffordOperator(SingleQubitOperator(op), op.q), phases = true) + return SingleQubitOperator(c) end end diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index e924f4a64..a6c33e3d0 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -70,7 +70,12 @@ end @testset "SingleQubitOperator inv methods" begin for gate_type in [sHadamard, sX, sY, sZ, sId1 , sPhase, sInvPhase] - @test CliffordOperator(inv(SingleQubitOperator(gate_type(1))), 1) == inv(CliffordOperator(gate_type)) + @test CliffordOperator(inv(SingleQubitOperator(gate_type(1))), 1) == inv(CliffordOperator(gate_type)) @test CliffordOperator(inv(gate_type(1)), 1) == inv(CliffordOperator(gate_type)) end + for i in 1:1000 + random_op = random_clifford1(Random.GLOBAL_RNG, 1) + @test CliffordOperator(inv(random_op), 1) == inv(CliffordOperator(random_op, 1)) + @test CliffordOperator(inv(SingleQubitOperator(random_op)), 1) == inv(CliffordOperator(random_op, 1)) + end end From 0052748f4eeb82922e8ee77c0f1569bfdc4d742d Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 18:10:24 +0500 Subject: [PATCH 08/15] codereview suggestions --- src/symbolic_cliffords.jl | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index 16c65870a..629bfb01f 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -229,20 +229,10 @@ end random_clifford1(qubit) = random_clifford1(GLOBAL_RNG, qubit) function inv(op::SingleQubitOperator) - if op.xx && op.xz && !op.zx && op.zz && !op.px && !op.pz - return sInvPhase(op.q) - elseif op.xx && op.xz && !op.zx && op.zz && op.px && !op.pz - return sPhase(op.q) - else - c = LinearAlgebra.inv(CliffordOperator(SingleQubitOperator(op), op.q), phases = true) - return SingleQubitOperator(c) - end + c = LinearAlgebra.inv(CliffordOperator(SingleQubitOperator(op), op.q), phases = true) + return SingleQubitOperator(c) end -inv(p::sPhase) = sInvPhase(p.q) - -inv(p::sInvPhase) = sPhase(p.q) - inv(op::AbstractSingleQubitOperator) = inv(SingleQubitOperator(op)) ############################## From b970a7e8f9eb1f4c0151fd6b9f45213287f53aed Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 18:19:52 +0500 Subject: [PATCH 09/15] codereview suggestions --- test/test_symcliff.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index a6c33e3d0..0f5859dbb 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -73,7 +73,7 @@ end @test CliffordOperator(inv(SingleQubitOperator(gate_type(1))), 1) == inv(CliffordOperator(gate_type)) @test CliffordOperator(inv(gate_type(1)), 1) == inv(CliffordOperator(gate_type)) end - for i in 1:1000 + for i in 1:10 random_op = random_clifford1(Random.GLOBAL_RNG, 1) @test CliffordOperator(inv(random_op), 1) == inv(CliffordOperator(random_op, 1)) @test CliffordOperator(inv(SingleQubitOperator(random_op)), 1) == inv(CliffordOperator(random_op, 1)) From 7f75d73436f3eceaaef27a0033d105d0883c3b45 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Fri, 12 Jul 2024 19:12:47 +0500 Subject: [PATCH 10/15] codereview suggestions --- src/QuantumClifford.jl | 1 - src/symbolic_cliffords.jl | 7 +++---- test/test_symcliff.jl | 5 ++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/QuantumClifford.jl b/src/QuantumClifford.jl index de89d7a27..44fb23312 100644 --- a/src/QuantumClifford.jl +++ b/src/QuantumClifford.jl @@ -8,7 +8,6 @@ module QuantumClifford # TODO Significant performance improvements: many operations do not need phase=true if the Pauli operations commute import LinearAlgebra -import Base: inv using LinearAlgebra: inv, mul!, rank, Adjoint, dot import DataStructures using DataStructures: DefaultDict, Accumulator diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index 629bfb01f..b87e80e38 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -1,5 +1,4 @@ using Random: AbstractRNG, GLOBAL_RNG -import Base: inv """Supertype of all symbolic operators. Subtype of `AbstractCliffordOperator`""" abstract type AbstractSymbolicOperator <: AbstractCliffordOperator end @@ -228,12 +227,12 @@ function random_clifford1(rng::AbstractRNG, qubit) end random_clifford1(qubit) = random_clifford1(GLOBAL_RNG, qubit) -function inv(op::SingleQubitOperator) - c = LinearAlgebra.inv(CliffordOperator(SingleQubitOperator(op), op.q), phases = true) +function LinearAlgebra.inv(op::SingleQubitOperator) + c = LinearAlgebra.inv(CliffordOperator(SingleQubitOperator(op), 1, compact=true)) return SingleQubitOperator(c) end -inv(op::AbstractSingleQubitOperator) = inv(SingleQubitOperator(op)) +LinearAlgebra.inv(op::AbstractSingleQubitOperator) = LinearAlgebra.inv(SingleQubitOperator(op)) ############################## # Two-qubit gates diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 0f5859dbb..33992bcfe 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -1,6 +1,5 @@ using Random using QuantumClifford -import Base: inv using QuantumClifford: CliffordOperator using QuantumClifford: stab_looks_good, destab_looks_good, mixed_stab_looks_good, mixed_destab_looks_good using QuantumClifford: apply_single_x!, apply_single_y!, apply_single_z! @@ -70,8 +69,8 @@ end @testset "SingleQubitOperator inv methods" begin for gate_type in [sHadamard, sX, sY, sZ, sId1 , sPhase, sInvPhase] - @test CliffordOperator(inv(SingleQubitOperator(gate_type(1))), 1) == inv(CliffordOperator(gate_type)) - @test CliffordOperator(inv(gate_type(1)), 1) == inv(CliffordOperator(gate_type)) + @test CliffordOperator(inv(SingleQubitOperator(gate_type(rand(1:100)))), 1) == inv(CliffordOperator(gate_type)) + @test CliffordOperator(inv(gate_type(rand(1:100))), 1) == inv(CliffordOperator(gate_type)) end for i in 1:10 random_op = random_clifford1(Random.GLOBAL_RNG, 1) From 09518753284b505eeb05a0e37b4b3e3d22e0df52 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 13 Jul 2024 05:07:16 +0500 Subject: [PATCH 11/15] minor fix to tests --- test/test_symcliff.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 33992bcfe..51d5c9443 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -69,8 +69,9 @@ end @testset "SingleQubitOperator inv methods" begin for gate_type in [sHadamard, sX, sY, sZ, sId1 , sPhase, sInvPhase] - @test CliffordOperator(inv(SingleQubitOperator(gate_type(rand(1:100)))), 1) == inv(CliffordOperator(gate_type)) - @test CliffordOperator(inv(gate_type(rand(1:100))), 1) == inv(CliffordOperator(gate_type)) + n = rand(1:100) + @test CliffordOperator(inv(SingleQubitOperator(gate_type(1))), n) == inv(CliffordOperator(gate_type(1), n)) + @test CliffordOperator(inv(gate_type(1)), n) == inv(CliffordOperator(gate_type(1), n)) end for i in 1:10 random_op = random_clifford1(Random.GLOBAL_RNG, 1) From 867d70e27de0c08b4650558a97d02f98de316789 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 13 Jul 2024 08:13:22 +0500 Subject: [PATCH 12/15] Fixing the error for gate_type(rand(1:100)) --- src/symbolic_cliffords.jl | 2 +- test/test_symcliff.jl | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index b87e80e38..ff5b90e3a 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -229,7 +229,7 @@ random_clifford1(qubit) = random_clifford1(GLOBAL_RNG, qubit) function LinearAlgebra.inv(op::SingleQubitOperator) c = LinearAlgebra.inv(CliffordOperator(SingleQubitOperator(op), 1, compact=true)) - return SingleQubitOperator(c) + return SingleQubitOperator(c, op.q) end LinearAlgebra.inv(op::AbstractSingleQubitOperator) = LinearAlgebra.inv(SingleQubitOperator(op)) diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 51d5c9443..689a30c79 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -70,8 +70,8 @@ end @testset "SingleQubitOperator inv methods" begin for gate_type in [sHadamard, sX, sY, sZ, sId1 , sPhase, sInvPhase] n = rand(1:100) - @test CliffordOperator(inv(SingleQubitOperator(gate_type(1))), n) == inv(CliffordOperator(gate_type(1), n)) - @test CliffordOperator(inv(gate_type(1)), n) == inv(CliffordOperator(gate_type(1), n)) + @test CliffordOperator(inv(SingleQubitOperator(gate_type(n))), n) == inv(CliffordOperator(gate_type(n), n)) + @test CliffordOperator(inv(gate_type(n)), n) == inv(CliffordOperator(gate_type(n), n)) end for i in 1:10 random_op = random_clifford1(Random.GLOBAL_RNG, 1) From 02a5c2bea39d921aaf408ee719ea316a8412f428 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 13 Jul 2024 08:39:02 +0500 Subject: [PATCH 13/15] reverting back to concrete enumerated inversion rules --- src/symbolic_cliffords.jl | 8 +++++++- test/test_symcliff.jl | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/symbolic_cliffords.jl b/src/symbolic_cliffords.jl index ff5b90e3a..0d2c26c40 100644 --- a/src/symbolic_cliffords.jl +++ b/src/symbolic_cliffords.jl @@ -232,7 +232,13 @@ function LinearAlgebra.inv(op::SingleQubitOperator) return SingleQubitOperator(c, op.q) end -LinearAlgebra.inv(op::AbstractSingleQubitOperator) = LinearAlgebra.inv(SingleQubitOperator(op)) +LinearAlgebra.inv(h::sHadamard) = sHadamard(h.q) +LinearAlgebra.inv(p::sPhase) = sInvPhase(p.q) +LinearAlgebra.inv(p::sInvPhase) = sPhase(p.q) +LinearAlgebra.inv(p::sId1) = sId1(p.q) +LinearAlgebra.inv(p::sX) = sX(p.q) +LinearAlgebra.inv(p::sY) = sY(p.q) +LinearAlgebra.inv(p::sZ) = sZ(p.q) ############################## # Two-qubit gates diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 689a30c79..ea08e101a 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -78,4 +78,11 @@ end @test CliffordOperator(inv(random_op), 1) == inv(CliffordOperator(random_op, 1)) @test CliffordOperator(inv(SingleQubitOperator(random_op)), 1) == inv(CliffordOperator(random_op, 1)) end + @test inv(sHadamard(1)) == sHadamard(1) + @test inv(sX(1)) == sX(1) + @test inv(sY(1)) == sY(1) + @test inv(sZ(1)) == sZ(1) + @test inv(sId1(1)) == sId1(1) + @test inv(sPhase(1)) == sInvPhase(1) + @test inv(sInvPhase(1)) == sPhase(1) end From f0fe933ce25b28d24a43cb695328f6583d40e753 Mon Sep 17 00:00:00 2001 From: Fe-r-oz Date: Sat, 13 Jul 2024 08:50:25 +0500 Subject: [PATCH 14/15] Minor formatting --- test/test_symcliff.jl | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index ea08e101a..689a30c79 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -78,11 +78,4 @@ end @test CliffordOperator(inv(random_op), 1) == inv(CliffordOperator(random_op, 1)) @test CliffordOperator(inv(SingleQubitOperator(random_op)), 1) == inv(CliffordOperator(random_op, 1)) end - @test inv(sHadamard(1)) == sHadamard(1) - @test inv(sX(1)) == sX(1) - @test inv(sY(1)) == sY(1) - @test inv(sZ(1)) == sZ(1) - @test inv(sId1(1)) == sId1(1) - @test inv(sPhase(1)) == sInvPhase(1) - @test inv(sInvPhase(1)) == sPhase(1) end From 5280f11ab22b19846e06ef2a38b651936ac12537 Mon Sep 17 00:00:00 2001 From: Stefan Krastanov Date: Wed, 17 Jul 2024 11:03:46 -0400 Subject: [PATCH 15/15] misc cleanup, mostly in tests --- CHANGELOG.md | 2 +- Project.toml | 2 +- test/test_symcliff.jl | 9 ++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6b787a92..ec4e15c24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ## v0.9.6 - 2024-07-12 -- `inv` implementation for the `SingleQubitOperator`. +- `inv` implementation for single-qubit "symbolic" Clifford operators (subtypes of `AbstractSingleQubitOperator`). ## v0.9.5 - 2024-07-04 diff --git a/Project.toml b/Project.toml index 92a6bbb5d..2f3303f4b 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.5" +version = "0.9.6" [deps] Combinatorics = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" diff --git a/test/test_symcliff.jl b/test/test_symcliff.jl index 689a30c79..2af1fd538 100644 --- a/test/test_symcliff.jl +++ b/test/test_symcliff.jl @@ -1,6 +1,5 @@ using Random using QuantumClifford -using QuantumClifford: CliffordOperator using QuantumClifford: stab_looks_good, destab_looks_good, mixed_stab_looks_good, mixed_destab_looks_good using QuantumClifford: apply_single_x!, apply_single_y!, apply_single_z! using InteractiveUtils @@ -69,13 +68,13 @@ end @testset "SingleQubitOperator inv methods" begin for gate_type in [sHadamard, sX, sY, sZ, sId1 , sPhase, sInvPhase] - n = rand(1:100) + n = rand(1:10) @test CliffordOperator(inv(SingleQubitOperator(gate_type(n))), n) == inv(CliffordOperator(gate_type(n), n)) @test CliffordOperator(inv(gate_type(n)), n) == inv(CliffordOperator(gate_type(n), n)) end for i in 1:10 - random_op = random_clifford1(Random.GLOBAL_RNG, 1) - @test CliffordOperator(inv(random_op), 1) == inv(CliffordOperator(random_op, 1)) - @test CliffordOperator(inv(SingleQubitOperator(random_op)), 1) == inv(CliffordOperator(random_op, 1)) + random_op = random_clifford1(i) + @test CliffordOperator(inv(random_op), i) == inv(CliffordOperator(random_op, i)) + @test CliffordOperator(inv(SingleQubitOperator(random_op)), i) == inv(CliffordOperator(random_op, i)) end end