Skip to content

Commit 1ce289b

Browse files
committed
add docs, tests and fixes for apply_right!
1 parent 66f41be commit 1ce289b

File tree

4 files changed

+119
-29
lines changed

4 files changed

+119
-29
lines changed

src/apply_right.jl

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,57 @@
1-
"""the `apply_right!` function is used to right multiply any quantum operation to unitary
2-
Clifford operation or Pauli product"""
1+
"""
2+
the `apply_right!` function is used to right multiply any quantum operation to unitary
3+
Clifford operation or Pauli product
4+
5+
```jldoctest
6+
julia> apply_right!(C"X Z", sHadamard(1))
7+
X₁ ⟼ + Z
8+
Z₁ ⟼ + X
9+
10+
julia> cliff = one(CliffordOperator, 2)
11+
X₁ ⟼ + X_
12+
X₂ ⟼ + _X
13+
Z₁ ⟼ + Z_
14+
Z₂ ⟼ + _Z
15+
julia> apply_right!(cliff, sHadamard(1))
16+
X₁ ⟼ + Z_
17+
X₂ ⟼ + _X
18+
Z₁ ⟼ + X_
19+
Z₂ ⟼ + _Z
20+
julia> apply_right!(cliff, sCNOT(1, 2))
21+
X₁ ⟼ + ZX
22+
X₂ ⟼ + _X
23+
Z₁ ⟼ + X_
24+
Z₂ ⟼ + XZ
25+
26+
julia> apply_right!(C"Y Z", C"Z Y"; phases=true)
27+
X₁ ⟼ + Z
28+
Z₁ ⟼ - X
29+
julia> apply_right!(C"Y Z", P"X")
30+
X₁ ⟼ + Y
31+
Z₁ ⟼ - Z
32+
```
33+
34+
See also: [`apply!`](@ref), [`apply_inv!`](@ref)
35+
"""
336
function apply_right! end
437

538

6-
# dense_cliffords
39+
##############################
40+
# Dense operators
41+
##############################
742

8-
function apply_right!(l::CliffordOperator, r::PauliOperator; phases=false)
43+
function apply_right!(l::CliffordOperator, r::PauliOperator)
944
nqubits(l)==nqubits(r) || throw(DimensionMismatch("The Clifford and Pauli operators need to act on the same number of qubits."))
10-
tab(l).phases[nqubits(l)+1:end] .⊻= r[1:nqubits(l)]
11-
tab(l).phases[1:nqubits(l)] .⊻= r[nqubits(l)+1:end]
45+
for i in 1:nqubits(l)
46+
x, z = r[i]
47+
if x
48+
phases(l)[nqubits(l)+i] ⊻= 0x02
49+
end
50+
if z
51+
phases(l)[i] ⊻= 0x02
52+
end
53+
end
54+
return l
1255
end
1356

1457
function apply_right!(l::CliffordOperator, r::CliffordOperator; phases=true)
@@ -47,15 +90,6 @@ end
4790
end
4891

4992

50-
# symbolic_cliffords
51-
52-
function mul_right_ignore_anticommute!(l::PauliOperator, r::PauliOperator)
53-
x = mul_right!(l, r; phases=Val(true))
54-
x.phase[] = x.phase[] & 0x02
55-
return x
56-
end
57-
58-
5993
##############################
6094
# Single-qubit gates
6195
##############################
@@ -89,18 +123,18 @@ function apply_right!(l::CliffordOperator, r::sInvPhase)
89123
end
90124

91125
function apply_right!(l::CliffordOperator, r::sX)
92-
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
126+
phases(l)[nqubits(l)+r.q] ⊻= 0x02
93127
return l
94128
end
95129

96130
function apply_right!(l::CliffordOperator, r::sY)
97-
phases(tab(l))[r.q] ⊻= 0x02
98-
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
131+
phases(l)[r.q] ⊻= 0x02
132+
phases(l)[nqubits(l)+r.q] ⊻= 0x02
99133
return l
100134
end
101135

102136
function apply_right!(l::CliffordOperator, r::sZ)
103-
phases(tab(l))[r.q] ⊻= 0x02
137+
phases(l)[r.q] ⊻= 0x02
104138
return l
105139
end
106140

@@ -116,14 +150,14 @@ function apply_right!(l::CliffordOperator, r::sInvSQRTX)
116150
end
117151

118152
function apply_right!(l::CliffordOperator, r::sSQRTY)
119-
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
153+
phases(l)[nqubits(l)+r.q] ⊻= 0x02
120154
rowswap!(tab(l), r.q, nqubits(l)+r.q)
121155
return l
122156
end
123157

124158
function apply_right!(l::CliffordOperator, r::sInvSQRTY)
125159
rowswap!(tab(l), r.q, nqubits(l)+r.q)
126-
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
160+
phases(l)[nqubits(l)+r.q] ⊻= 0x02
127161
return l
128162
end
129163

@@ -270,7 +304,7 @@ function apply_right!(l::CliffordOperator, r::sInvZCrY)
270304
l[r.q2] = mul_left!(l[r.q2], l[nqubits(l)+r.q1])
271305
l[nqubits(l)+r.q2] = mul_left!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1])
272306
l[r.q1] = mul_left!(l[r.q1], l[nqubits(l)+r.q2])
273-
phases(tab(l))[r.q1] ⊻= 0x02
307+
phases(l)[r.q1] ⊻= 0x02
274308
return l
275309
end
276310

@@ -322,4 +356,13 @@ function apply_right!(l::CliffordOperator, r::sInvSQRTYY)
322356
rowswap!(tab(l), r.q2, nqubits(l)+r.q2)
323357
apply_right!(l, sZ(r.q2))
324358
return l
359+
end
360+
361+
362+
"""Multiply Pauli operators `l * r`, ignoring anticommutation phases (keeping only ±1, not ±i).
363+
See also: [`mul_right!`](@ref)."""
364+
function mul_right_ignore_anticommute!(l::PauliOperator, r::PauliOperator)
365+
mul_right!(l, r; phases=Val(true))
366+
l.phase[] = l.phase[] & 0x02
367+
return l
325368
end

src/dense_cliffords.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ function Base.copy(c::CliffordOperator)
9191
end
9292

9393
@inline nqubits(c::CliffordOperator) = nqubits(tab(c))
94+
@inline phases(c::CliffordOperator) = phases(tab(c))
9495

9596
Base.zero(c::CliffordOperator) = CliffordOperator(zero(tab(c)))
9697
Base.zero(::Type{<:CliffordOperator}, n) = CliffordOperator(zero(Tableau, 2n, n))

test/test_apply_right.jl

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,78 @@
11
@testitem "Apply Right" begin
22
using InteractiveUtils
3-
using QuantumClifford: AbstractCliffordOperator
3+
using QuantumClifford: AbstractCliffordOperator, CliffordOperator
4+
5+
test_sizes = [1,2,63,64,65,127,128,129,511,512,513]
6+
7+
function CliffordOperator(pauli::PauliOperator)
8+
n = nqubits(pauli)
9+
res = one(CliffordOperator, n)
10+
11+
for i in 1:2n
12+
if comm(pauli, tab(res), i) == 0x1
13+
phases(res)[i] ⊻= 0x02
14+
end
15+
end
16+
return res
17+
end
18+
19+
@testset "CliffordOperator constructor from PauliOperator" begin
20+
for n in test_sizes
21+
l = random_clifford(n)
22+
pauli = random_pauli(n)
23+
@test isequal(apply!(copy(l), pauli; phases=true), apply!(l, CliffordOperator(pauli); phases=true))
24+
end
25+
end
426

527
# SLOW version of apply_right! for testing
28+
function apply_right_slow!(l::CliffordOperator, r::CliffordOperator; phases=true)
29+
apply!(r, l; phases)
30+
end
31+
function apply_right_slow!(l::CliffordOperator, r::PauliOperator; phases=true)
32+
apply!(CliffordOperator(r), l; phases)
33+
end
634
function apply_right_slow!(l::CliffordOperator, r::AbstractCliffordOperator; phases=true)
7-
apply!(CliffordOperator(r, nqubits(l)), l; phases=phases)
35+
apply!(CliffordOperator(r, nqubits(l)), l; phases)
36+
end
37+
38+
@testset "Apply Right dense operators" begin
39+
for q in test_sizes
40+
l = random_clifford(q)
41+
cliff = random_clifford(q)
42+
pauli = random_pauli(q)
43+
44+
@test isequal(apply_right!(copy(l), cliff), apply_right_slow!(l, cliff))
45+
@inferred apply_right!(copy(l), cliff)
46+
47+
@test isequal(apply_right!(copy(l), pauli), apply_right_slow!(l, pauli))
48+
@inferred apply_right!(copy(l), pauli)
49+
end
850
end
9-
10-
q = 64
11-
shots = 16
1251

1352
@testset "Apply Right single-qubit" begin
14-
for _ in 1:shots
53+
for q in test_sizes
1554
l = random_clifford(q)
1655
q1 = rand(1:q)
1756

1857
for gate in subtypes(AbstractSingleQubitOperator)
1958
gate == SingleQubitOperator && continue
59+
2060
@test isequal(apply_right!(copy(l), gate(q1)), apply_right_slow!(l, gate(q1)))
61+
@inferred apply_right!(copy(l), gate(q1))
2162
end
2263
end
2364
end
2465

2566
@testset "Apply Right two-qubit" begin
26-
for _ in 1:shots
67+
for q in test_sizes
68+
q < 2 && continue
69+
2770
l = random_clifford(q)
2871
q1 = rand(1:q); q2 = rand(setdiff(1:q, [q1]))
2972

3073
for gate in subtypes(AbstractTwoQubitOperator)
3174
@test isequal(apply_right!(copy(l), gate(q1, q2)), apply_right_slow!(l, gate(q1, q2)))
75+
@inferred apply_right!(copy(l), gate(q1, q2))
3276
end
3377
end
3478
end

test/test_throws.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,6 @@
7171
@test_throws DimensionMismatch Stabilizer(fill(0x0, 2), Matrix{Bool}([1 0 1;1 1 1; 1 0 1]), Matrix{Bool}([1 0 0;1 1 1;1 0 1]))
7272
@test_throws DimensionMismatch Stabilizer(fill(0x0, 2), Matrix{Bool}([1 0 1 1 0 0; 1 1 1 1 1 1; 1 0 1 1 0 1]))
7373

74+
@test_throws DimensionMismatch apply_right!(random_clifford(1), random_pauli(2))
75+
@test_throws DimensionMismatch apply_right!(random_clifford(2), random_clifford(1))
7476
end

0 commit comments

Comments
 (0)