Skip to content

Commit 3a5f82a

Browse files
committed
complete two-qubit gates
1 parent 5b1c6da commit 3a5f82a

File tree

2 files changed

+95
-78
lines changed

2 files changed

+95
-78
lines changed

src/apply_right.jl

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,54 @@
1-
"""the `apply_right!` function is used to prepend any quantum operation to unitary Clifford operation"""
1+
"""the `apply_right!` function is used to right multiply any quantum operation to unitary
2+
Clifford operation or Pauli product"""
23
function apply_right! end
34

4-
function apply_right!(l::CliffordOperator, r::AbstractCliffordOperator; phases=true)
5-
@warn "Slow apply_right! operation: $r"
6-
apply!(CliffordOperator(r, nqubits(l)), l; phases=phases)
7-
end
85

9-
# helper
6+
# dense_cliffords
7+
8+
function apply_right!(l::CliffordOperator, r::PauliOperator; phases=false)
9+
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]
12+
end
13+
14+
function apply_right!(l::CliffordOperator, r::CliffordOperator; phases=true)
15+
nqubits(l)==nqubits(r) || throw(DimensionMismatch("The two Clifford operators need to act on the same number of qubits."))
16+
l_tab = tab(l)
17+
r_tab = tab(r)
18+
threadlocal = l.buffer
19+
new_xzs = Vector{typeof(threadlocal)}(undef, length(l_tab))
20+
@inbounds for row_r in eachindex(r_tab)
21+
zero!(threadlocal)
22+
apply_right_row_kernel!(threadlocal, row_r, l_tab, r_tab, phases=phases)
23+
new_xzs[row_r] = copy(threadlocal)
24+
end
25+
@inbounds for row_l in eachindex(l_tab)
26+
l_tab[row_l] = new_xzs[row_l]
27+
end
28+
l
29+
end
30+
31+
@inline function apply_right_row_kernel!(new_lrow, row, l_tab, r_tab; phases=true)
32+
phases && (new_lrow.phase[] = r_tab.phases[row])
33+
n = nqubits(l_tab)
34+
for qubit in 1:n
35+
x,z = r_tab[row,qubit]
36+
if phases&&x&&z
37+
new_lrow.phase[] -= 0x1
38+
end
39+
if x
40+
mul_left!(new_lrow, l_tab, qubit, phases=Val(phases))
41+
end
42+
if z
43+
mul_left!(new_lrow, l_tab, qubit+n, phases=Val(phases))
44+
end
45+
end
46+
new_lrow
47+
end
48+
49+
50+
# symbolic_cliffords
51+
1052
function mul_right_ignore_anticommute!(l::PauliOperator, r::PauliOperator)
1153
x = mul_right!(l, r; phases=Val(true))
1254
x.phase[] = x.phase[] & 0x02
@@ -36,7 +78,7 @@ function apply_right!(l::CliffordOperator, r::sHadamardYZ)
3678
end
3779

3880
function apply_right!(l::CliffordOperator, r::sPhase)
39-
l[r.q] = mul_right_ignore_anticommute!(l[r.q], l[nqubits(l)+r.q])
81+
apply_right!(l, sInvPhase(r.q))
4082
apply_right!(l, sZ(r.q))
4183
return l
4284
end
@@ -85,17 +127,6 @@ function apply_right!(l::CliffordOperator, r::sInvSQRTY)
85127
return l
86128
end
87129

88-
function apply_right!(l::CliffordOperator, r::sPhase)
89-
apply_right!(l, sInvPhase(r.q))
90-
apply_right!(l, sZ(r.q))
91-
return l
92-
end
93-
94-
function apply_right!(l::CliffordOperator, r::sInvPhase)
95-
l[r.q] = mul_right_ignore_anticommute!(l[r.q], l[nqubits(l)+r.q])
96-
return l
97-
end
98-
99130
function apply_right!(l::CliffordOperator, r::sCXYZ)
100131
rowswap!(tab(l), r.q, nqubits(l)+r.q)
101132
l[r.q] = mul_right_ignore_anticommute!(l[r.q], l[nqubits(l)+r.q])
@@ -124,14 +155,17 @@ function apply_right!(l::CliffordOperator, r::sSWAP)
124155
return l
125156
end
126157

127-
# function apply_right!(l::CliffordOperator, r::sSWAPCX)
128-
# rowswap!(tab(l), r.q1, r.q2)
129-
# return l
130-
# end
158+
function apply_right!(l::CliffordOperator, r::sSWAPCX)
159+
apply_right!(l, sSWAP(r.q1, r.q2))
160+
apply_right!(l, sCNOT(r.q2, r.q1))
161+
return l
162+
end
131163

132-
# function apply_right!(l::CliffordOperator, r::sInvSWAPCX)
133-
# return l
134-
# end
164+
function apply_right!(l::CliffordOperator, r::sInvSWAPCX)
165+
apply_right!(l, sCNOT(r.q2, r.q1))
166+
apply_right!(l, sSWAP(r.q1, r.q2))
167+
return l
168+
end
135169

136170
function apply_right!(l::CliffordOperator, r::sISWAP)
137171
apply_right!(l, sSWAP(r.q1, r.q2))
@@ -149,21 +183,26 @@ function apply_right!(l::CliffordOperator, r::sInvISWAP)
149183
return l
150184
end
151185

152-
# function apply_right!(l::CliffordOperator, r::sCZSWAP)
153-
# return l
154-
# end
186+
function apply_right!(l::CliffordOperator, r::sCZSWAP)
187+
apply_right!(l, sZCZ(r.q2, r.q1))
188+
apply_right!(l, sSWAP(r.q1, r.q2))
189+
return l
190+
end
155191

156-
# function apply_right!(l::CliffordOperator, r::sCXSWAP)
157-
# return l
158-
# end
192+
function apply_right!(l::CliffordOperator, r::sCXSWAP)
193+
apply_right!(l, sCNOT(r.q2, r.q1))
194+
apply_right!(l, sSWAP(r.q1, r.q2))
195+
return l
196+
end
159197

160198
function apply_right!(l::CliffordOperator, r::sCNOT)
161199
return apply_right!(l, sZCX(r.q1, r.q2))
162200
end
163201

164-
# function apply_right!(l::CliffordOperator, r::sCPHASE)
165-
# return l
166-
# end
202+
function apply_right!(l::CliffordOperator, r::sCPHASE)
203+
apply_right!(l, sZCZ(r.q1, r.q2))
204+
return l
205+
end
167206

168207
function apply_right!(l::CliffordOperator, r::sZCX)
169208
l[nqubits(l)+r.q2] = mul_right!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1]; phases=Val(true))
@@ -218,13 +257,22 @@ function apply_right!(l::CliffordOperator, r::sYCZ)
218257
return apply_right!(l, sZCY(r.q2, r.q1))
219258
end
220259

221-
# function apply_right!(l::CliffordOperator, r::sZCrY)
222-
# return l
223-
# end
260+
function apply_right!(l::CliffordOperator, r::sZCrY)
261+
l[r.q1] = mul_left!(l[r.q1], l[r.q2])
262+
l[r.q2] = mul_left!(l[r.q2], l[nqubits(l)+r.q1])
263+
l[nqubits(l)+r.q2] = mul_left!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1])
264+
l[r.q1] = mul_left!(l[r.q1], l[nqubits(l)+r.q2])
265+
return l
266+
end
224267

225-
# function apply_right!(l::CliffordOperator, r::sInvZCrY)
226-
# return l
227-
# end
268+
function apply_right!(l::CliffordOperator, r::sInvZCrY)
269+
l[r.q1] = mul_left!(l[r.q1], l[r.q2])
270+
l[r.q2] = mul_left!(l[r.q2], l[nqubits(l)+r.q1])
271+
l[nqubits(l)+r.q2] = mul_left!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1])
272+
l[r.q1] = mul_left!(l[r.q1], l[nqubits(l)+r.q2])
273+
phases(tab(l))[r.q1] ⊻= 0x02
274+
return l
275+
end
228276

229277
function apply_right!(l::CliffordOperator, r::sSQRTZZ)
230278
apply_right!(l, sInvSQRTZZ(r.q1, r.q2))

test/test_apply_right.jl

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,6 @@
1010
q = 64
1111
shots = 16
1212

13-
# @testset "Apply Right single-qubit" begin
14-
# for gate in subtypes(AbstractSingleQubitOperator)
15-
# if gate in [sPhase, sInvPhase, SingleQubitOperator, sCXYZ, sCZYX]
16-
# continue
17-
# end
18-
# r = gate(rand(1:q))
19-
20-
# for _ in 1:shots
21-
# l = random_clifford(q)
22-
# @test isequal(apply_right!(copy(l), r), apply_right_slow!(l, r))
23-
# end
24-
# end
25-
# end
26-
27-
# @testset "Apply Right two-qubit" begin
28-
# for gate in subtypes(AbstractTwoQubitOperator)
29-
# if gate in [sSWAPCX, sInvSWAPCX, sCZSWAP, sCXSWAP, sCPHASE, sZCrY, sInvZCrY]
30-
# continue
31-
# end
32-
# q1 = rand(1:q); q2 = rand(setdiff(1:q, [q1]))
33-
# r = gate(q1, q2)
34-
35-
# for _ in 1:shots
36-
# l = random_clifford(q)
37-
# @test isequal(apply_right!(copy(l), r), apply_right_slow!(l, r))
38-
# end
39-
# end
40-
# end
41-
4213
@testset "Apply Right single-qubit" begin
4314
for _ in 1:shots
4415
l = random_clifford(q)
@@ -56,8 +27,6 @@
5627
@test isequal(apply_right!(copy(l), sInvSQRTX(q1)), apply_right_slow!(l, sInvSQRTX(q1)))
5728
@test isequal(apply_right!(copy(l), sSQRTY(q1)), apply_right_slow!(l, sSQRTY(q1)))
5829
@test isequal(apply_right!(copy(l), sInvSQRTY(q1)), apply_right_slow!(l, sInvSQRTY(q1)))
59-
# @test isequal(apply_right!(copy(l), sSQRTZ(q1)), apply_right_slow!(l, sSQRTZ(q1)))
60-
# @test isequal(apply_right!(copy(l), sInvSQRTZ(q1)), apply_right_slow!(l, sInvSQRTZ(q1)))
6130
@test isequal(apply_right!(copy(l), sCXYZ(q1)), apply_right_slow!(l, sCXYZ(q1)))
6231
@test isequal(apply_right!(copy(l), sCZYX(q1)), apply_right_slow!(l, sCZYX(q1)))
6332
@test isequal(apply_right!(copy(l), sId1(q1)), apply_right_slow!(l, sId1(q1)))
@@ -70,14 +39,14 @@
7039
q1 = rand(1:q); q2 = rand(setdiff(1:q, [q1]))
7140

7241
@test isequal(apply_right!(copy(l), sSWAP(q1, q2)), apply_right_slow!(l, sSWAP(q1, q2)))
73-
# @test isequal(apply_right!(copy(l), sSWAPCX(q1, q2)), apply_right_slow!(l, sSWAPCX(q1, q2)))
74-
# @test isequal(apply_right!(copy(l), sInvSWAPCX(q1, q2)), apply_right_slow!(l, sInvSWAPCX(q1, q2)))
42+
@test isequal(apply_right!(copy(l), sSWAPCX(q1, q2)), apply_right_slow!(l, sSWAPCX(q1, q2)))
43+
@test isequal(apply_right!(copy(l), sInvSWAPCX(q1, q2)), apply_right_slow!(l, sInvSWAPCX(q1, q2)))
7544
@test isequal(apply_right!(copy(l), sISWAP(q1, q2)), apply_right_slow!(l, sISWAP(q1, q2)))
7645
@test isequal(apply_right!(copy(l), sInvISWAP(q1, q2)), apply_right_slow!(l, sInvISWAP(q1, q2)))
77-
# @test isequal(apply_right!(copy(l), sCZSWAP(q1, q2)), apply_right_slow!(l, sCZSWAP(q1, q2)))
78-
# @test isequal(apply_right!(copy(l), sCXSWAP(q1, q2)), apply_right_slow!(l, sCXSWAP(q1, q2)))
46+
@test isequal(apply_right!(copy(l), sCZSWAP(q1, q2)), apply_right_slow!(l, sCZSWAP(q1, q2)))
47+
@test isequal(apply_right!(copy(l), sCXSWAP(q1, q2)), apply_right_slow!(l, sCXSWAP(q1, q2)))
7948
@test isequal(apply_right!(copy(l), sCNOT(q1, q2)), apply_right_slow!(l, sCNOT(q1, q2)))
80-
# @test isequal(apply_right!(copy(l), sCPHASE(q1, q2)), apply_right_slow!(l, sCPHASE(q1, q2)))
49+
@test isequal(apply_right!(copy(l), sCPHASE(q1, q2)), apply_right_slow!(l, sCPHASE(q1, q2)))
8150
@test isequal(apply_right!(copy(l), sZCX(q1, q2)), apply_right_slow!(l, sZCX(q1, q2)))
8251
@test isequal(apply_right!(copy(l), sZCY(q1, q2)), apply_right_slow!(l, sZCY(q1, q2)))
8352
@test isequal(apply_right!(copy(l), sZCZ(q1, q2)), apply_right_slow!(l, sZCZ(q1, q2)))
@@ -87,8 +56,8 @@
8756
@test isequal(apply_right!(copy(l), sYCX(q1, q2)), apply_right_slow!(l, sYCX(q1, q2)))
8857
@test isequal(apply_right!(copy(l), sYCY(q1, q2)), apply_right_slow!(l, sYCY(q1, q2)))
8958
@test isequal(apply_right!(copy(l), sYCZ(q1, q2)), apply_right_slow!(l, sYCZ(q1, q2)))
90-
# @test isequal(apply_right!(copy(l), sZCrY(q1, q2)), apply_right_slow!(l, sZCrY(q1, q2)))
91-
# @test isequal(apply_right!(copy(l), sInvZCrY(q1, q2)), apply_right_slow!(l, sInvZCrY(q1, q2)))
59+
@test isequal(apply_right!(copy(l), sZCrY(q1, q2)), apply_right_slow!(l, sZCrY(q1, q2)))
60+
@test isequal(apply_right!(copy(l), sInvZCrY(q1, q2)), apply_right_slow!(l, sInvZCrY(q1, q2)))
9261
@test isequal(apply_right!(copy(l), sSQRTZZ(q1, q2)), apply_right_slow!(l, sSQRTZZ(q1, q2)))
9362
@test isequal(apply_right!(copy(l), sInvSQRTZZ(q1, q2)), apply_right_slow!(l, sInvSQRTZZ(q1, q2)))
9463
@test isequal(apply_right!(copy(l), sSQRTXX(q1, q2)), apply_right_slow!(l, sSQRTXX(q1, q2)))

0 commit comments

Comments
 (0)