Skip to content

Commit fe3ae66

Browse files
committed
initial commit
1 parent d86ff67 commit fe3ae66

File tree

3 files changed

+351
-1
lines changed

3 files changed

+351
-1
lines changed

src/QuantumClifford.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export
4040
# Linear Algebra
4141
tensor, tensor_pow,
4242
logdot, expect,
43-
apply!, apply_inv!,
43+
apply!, apply_inv!, apply_right!,
4444
permutesystems, permutesystems!,
4545
# Low Level Function Interface
4646
generate!, project!, reset_qubits!, traceout!,
@@ -1460,5 +1460,6 @@ include("grouptableaux.jl")
14601460
include("plotting_extensions.jl")
14611461
#
14621462
include("gpu_adapters.jl")
1463+
include("apply_right.jl")
14631464

14641465
end #module

src/apply_right.jl

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
"""the `apply_right!` function is used to prepend any quantum operation to unitary Clifford operation"""
2+
function apply_right! end
3+
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
8+
9+
10+
##############################
11+
# Single-qubit gates
12+
##############################
13+
14+
function apply_right!(l::CliffordOperator, r::sHadamard)
15+
rowswap!(tab(l), r.q, nqubits(l)+r.q)
16+
return l
17+
end
18+
19+
function apply_right!(l::CliffordOperator, r::sHadamardXY)
20+
mul_right!(l[r.q], l[nqubits(l)+r.q]; phases=Val(false))
21+
apply_right!(l, sY(r.q))
22+
return l
23+
end
24+
25+
function apply_right!(l::CliffordOperator, r::sHadamardYZ)
26+
mul_right!(l[nqubits(l)+r.q], l[r.q]; phases=Val(false))
27+
apply_right!(l, sZ(r.q))
28+
return l
29+
end
30+
31+
function apply_right!(l::CliffordOperator, r::sPhase)
32+
mul_right!(l[r.q], l[nqubits(l)+r.q]; phases=Val(true))
33+
return l
34+
end
35+
36+
# function apply_right!(l::CliffordOperator, r::sInvPhase)
37+
# return l
38+
# end
39+
40+
function apply_right!(l::CliffordOperator, r::sX)
41+
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
42+
return l
43+
end
44+
45+
function apply_right!(l::CliffordOperator, r::sY)
46+
phases(tab(l))[r.q] ⊻= 0x02
47+
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
48+
return l
49+
end
50+
51+
function apply_right!(l::CliffordOperator, r::sZ)
52+
phases(tab(l))[r.q] ⊻= 0x02
53+
return l
54+
end
55+
56+
function apply_right!(l::CliffordOperator, r::sSQRTX)
57+
apply_right!(l, sInvSQRTX(r.q))
58+
apply_right!(l, sX(r.q))
59+
return l
60+
end
61+
62+
function apply_right!(l::CliffordOperator, r::sInvSQRTX)
63+
mul_right!(l[nqubits(l)+r.q], l[r.q]; phases=Val(false))
64+
return l
65+
end
66+
67+
function apply_right!(l::CliffordOperator, r::sSQRTY)
68+
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
69+
rowswap!(tab(l), r.q, nqubits(l)+r.q)
70+
return l
71+
end
72+
73+
function apply_right!(l::CliffordOperator, r::sInvSQRTY)
74+
rowswap!(tab(l), r.q, nqubits(l)+r.q)
75+
phases(tab(l))[nqubits(l)+r.q] ⊻= 0x02
76+
return l
77+
end
78+
79+
# function apply_right!(l::CliffordOperator, r::sCXYZ)
80+
# return l
81+
# end
82+
83+
# function apply_right!(l::CliffordOperator, r::sCZYX)
84+
# return l
85+
# end
86+
87+
function apply_right!(l::CliffordOperator, r::sId1)
88+
return l
89+
end
90+
91+
92+
##############################
93+
# Two-qubit gates
94+
##############################
95+
96+
function apply_right!(l::CliffordOperator, r::sSWAP)
97+
rowswap!(tab(l), nqubits(l)+r.q1, nqubits(l)+r.q2)
98+
rowswap!(tab(l), r.q1, r.q2)
99+
return l
100+
end
101+
102+
# function apply_right!(l::CliffordOperator, r::sSWAPCX)
103+
# return l
104+
# end
105+
106+
# function apply_right!(l::CliffordOperator, r::sInvSWAPCX)
107+
# return l
108+
# end
109+
110+
function apply_right!(l::CliffordOperator, r::sISWAP)
111+
apply_right!(l, sSWAP(r.q1, r.q2))
112+
apply_right!(l, sZCZ(r.q1, r.q2))
113+
apply_right!(l, sSQRTZ(r.q1))
114+
apply_right!(l, sSQRTZ(r.q2))
115+
return l
116+
end
117+
118+
function apply_right!(l::CliffordOperator, r::sInvISWAP)
119+
apply_right!(l, sSWAP(r.q1, r.q2))
120+
apply_right!(l, sZCZ(r.q1, r.q2))
121+
apply_right!(l, sInvSQRTZ(r.q1))
122+
apply_right!(l, sInvSQRTZ(r.q2))
123+
return l
124+
end
125+
126+
# function apply_right!(l::CliffordOperator, r::sCZSWAP)
127+
# return l
128+
# end
129+
130+
# function apply_right!(l::CliffordOperator, r::sCXSWAP)
131+
# return l
132+
# end
133+
134+
function apply_right!(l::CliffordOperator, r::sCNOT)
135+
return apply_right!(l, sZCX(r.q1, r.q2))
136+
end
137+
138+
# function apply_right!(l::CliffordOperator, r::sCPHASE)
139+
# return l
140+
# end
141+
142+
function apply_right!(l::CliffordOperator, r::sZCX)
143+
mul_right!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1]; phases=Val(true))
144+
mul_right!(l[r.q1], l[r.q2]; phases=Val(true))
145+
return l
146+
end
147+
148+
function apply_right!(l::CliffordOperator, r::sZCY)
149+
apply_right!(l, sHadamardYZ(r.q2))
150+
apply_right!(l, sZCZ(r.q1, r.q2))
151+
apply_right!(l, sHadamardYZ(r.q2))
152+
return l
153+
end
154+
155+
function apply_right!(l::CliffordOperator, r::sZCZ)
156+
mul_right!(l[r.q2], l[nqubits(l)+r.q1]; phases=Val(true))
157+
mul_right!(l[r.q1], l[nqubits(l)+r.q2]; phases=Val(true))
158+
return l
159+
end
160+
161+
function apply_right!(l::CliffordOperator, r::sXCX)
162+
mul_right!(l[nqubits(l)+r.q2], l[r.q1]; phases=Val(true))
163+
mul_right!(l[nqubits(l)+r.q1], l[r.q2]; phases=Val(true))
164+
return l
165+
end
166+
167+
function apply_right!(l::CliffordOperator, r::sXCY)
168+
apply_right!(l, sHadamardXY(r.q2))
169+
apply_right!(l, sXCX(r.q1, r.q2))
170+
apply_right!(l, sHadamardXY(r.q2))
171+
return l
172+
end
173+
174+
function apply_right!(l::CliffordOperator, r::sXCZ)
175+
return apply_right!(l, sZCX(r.q2, r.q1))
176+
end
177+
178+
function apply_right!(l::CliffordOperator, r::sYCX)
179+
return apply_right!(l, sXCY(r.q2, r.q1))
180+
end
181+
182+
function apply_right!(l::CliffordOperator, r::sYCY)
183+
apply_right!(l, sHadamardYZ(r.q1))
184+
apply_right!(l, sHadamardYZ(r.q2))
185+
apply_right!(l, sZCZ(r.q1, r.q2))
186+
apply_right!(l, sHadamardYZ(r.q2))
187+
apply_right!(l, sHadamardYZ(r.q1))
188+
return l
189+
end
190+
191+
function apply_right!(l::CliffordOperator, r::sYCZ)
192+
return apply_right!(l, sZCY(r.q2, r.q1))
193+
end
194+
195+
# function apply_right!(l::CliffordOperator, r::sZCrY)
196+
# return l
197+
# end
198+
199+
# function apply_right!(l::CliffordOperator, r::sInvZCrY)
200+
# return l
201+
# end
202+
203+
function apply_right!(l::CliffordOperator, r::sSQRTZZ)
204+
apply_right!(l, sInvSQRTZZ(r.q1, r.q2))
205+
apply_right!(l, sZ(r.q1))
206+
apply_right!(l, sZ(r.q2))
207+
return l
208+
end
209+
210+
function apply_right!(l::CliffordOperator, r::sInvSQRTZZ)
211+
mul_right!(l[r.q1], l[nqubits(l)+r.q1]; phases=Val(false))
212+
mul_right!(l[r.q1], l[nqubits(l)+r.q2]; phases=Val(false))
213+
mul_right!(l[r.q2], l[nqubits(l)+r.q1]; phases=Val(false))
214+
mul_right!(l[r.q2], l[nqubits(l)+r.q2]; phases=Val(false))
215+
return l
216+
end
217+
218+
function apply_right!(l::CliffordOperator, r::sSQRTXX)
219+
apply_right!(l, sInvSQRTXX(r.q1, r.q2))
220+
apply_right!(l, sX(r.q1))
221+
apply_right!(l, sX(r.q2))
222+
return l
223+
end
224+
225+
function apply_right!(l::CliffordOperator, r::sInvSQRTXX)
226+
mul_right!(l[nqubits(l)+r.q1], l[r.q1]; phases=Val(false))
227+
mul_right!(l[nqubits(l)+r.q1], l[r.q2]; phases=Val(false))
228+
mul_right!(l[nqubits(l)+r.q2], l[r.q1]; phases=Val(false))
229+
mul_right!(l[nqubits(l)+r.q2], l[r.q2]; phases=Val(false))
230+
return l
231+
end
232+
233+
function apply_right!(l::CliffordOperator, r::sSQRTYY)
234+
apply_right!(l, sInvSQRTYY(r.q1, r.q2))
235+
apply_right!(l, sY(r.q1))
236+
apply_right!(l, sY(r.q2))
237+
return l
238+
end
239+
240+
function apply_right!(l::CliffordOperator, r::sInvSQRTYY)
241+
mul_right!(l[r.q1], l[nqubits(l)+r.q1]; phases=Val(false))
242+
mul_right!(l[nqubits(l)+r.q1], l[nqubits(l)+r.q2]; phases=Val(false))
243+
mul_right!(l[nqubits(l)+r.q1], l[r.q2]; phases=Val(false))
244+
mul_right!(l[r.q2], l[r.q1]; phases=Val(false))
245+
mul_right!(l[nqubits(l)+r.q2], l[r.q1]; phases=Val(false))
246+
mul_right!(l[r.q1], l[nqubits(l)+r.q1]; phases=Val(false))
247+
rowswap!(tab(l), r.q1, nqubits(l)+r.q1)
248+
rowswap!(tab(l), r.q2, nqubits(l)+r.q2)
249+
apply_right!(l, sZ(r.q2))
250+
return l
251+
end

test/test_apply_right.jl

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
@testitem "Apply Right" begin
2+
using InteractiveUtils
3+
using QuantumClifford: AbstractCliffordOperator
4+
5+
# SLOW version of apply_right! for testing
6+
function apply_right_slow!(l::CliffordOperator, r::AbstractCliffordOperator; phases=true)
7+
apply!(CliffordOperator(r, nqubits(l)), l; phases=phases)
8+
end
9+
10+
q = 2
11+
shots = 1
12+
13+
# @testset "Apply Right single-qubit" begin
14+
# for gate in subtypes(AbstractSingleQubitOperator)
15+
# if gate in [sPhase, sInvPhase, SingleQubitOperator, sXYZ, sZYX]
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+
42+
@testset "Apply Right single-qubit" begin
43+
for _ in 1:shots
44+
l = random_clifford(q)
45+
q1 = rand(1:q)
46+
47+
@test isequal(apply_right!(copy(l), sHadamard(q1)), apply_right_slow!(l, sHadamard(q1)))
48+
@test isequal(apply_right!(copy(l), sHadamardXY(q1)), apply_right_slow!(l, sHadamardXY(q1)))
49+
@test isequal(apply_right!(copy(l), sHadamardYZ(q1)), apply_right_slow!(l, sHadamardYZ(q1)))
50+
@test isequal(apply_right!(copy(l), sPhase(q1)), apply_right_slow!(l, sPhase(q1)))
51+
# @test isequal(apply_right!(copy(l), sInvPhase(q1)), apply_right_slow!(l, sInvPhase(q1)))
52+
@test isequal(apply_right!(copy(l), sX(q1)), apply_right_slow!(l, sX(q1)))
53+
@test isequal(apply_right!(copy(l), sY(q1)), apply_right_slow!(l, sY(q1)))
54+
@test isequal(apply_right!(copy(l), sZ(q1)), apply_right_slow!(l, sZ(q1)))
55+
@test isequal(apply_right!(copy(l), sSQRTX(q1)), apply_right_slow!(l, sSQRTX(q1)))
56+
@test isequal(apply_right!(copy(l), sInvSQRTX(q1)), apply_right_slow!(l, sInvSQRTX(q1)))
57+
@test isequal(apply_right!(copy(l), sSQRTY(q1)), apply_right_slow!(l, sSQRTY(q1)))
58+
@test isequal(apply_right!(copy(l), sInvSQRTY(q1)), apply_right_slow!(l, sInvSQRTY(q1)))
59+
# @test isequal(apply_right!(copy(l), sCXYZ(q1)), apply_right_slow!(l, sCXYZ(q1)))
60+
# @test isequal(apply_right!(copy(l), sCZYX(q1)), apply_right_slow!(l, sCZYX(q1)))
61+
@test isequal(apply_right!(copy(l), sId1(q1)), apply_right_slow!(l, sId1(q1)))
62+
end
63+
end
64+
65+
# @testset "Apply Right two-qubit" begin
66+
# for _ in 1:shots
67+
# l = random_clifford(q)
68+
# q1 = rand(1:q); q2 = rand(setdiff(1:q, [q1]))
69+
70+
# @test isequal(apply_right!(copy(l), sSWAP(q1, q2)), apply_right_slow!(l, sSWAP(q1, q2)))
71+
# # @test isequal(apply_right!(copy(l), sSWAPCX(q1, q2)), apply_right_slow!(l, sSWAPCX(q1, q2)))
72+
# # @test isequal(apply_right!(copy(l), sInvSWAPCX(q1, q2)), apply_right_slow!(l, sInvSWAPCX(q1, q2)))
73+
# @test isequal(apply_right!(copy(l), sISWAP(q1, q2)), apply_right_slow!(l, sISWAP(q1, q2)))
74+
# @test isequal(apply_right!(copy(l), sInvISWAP(q1, q2)), apply_right_slow!(l, sInvISWAP(q1, q2)))
75+
# # @test isequal(apply_right!(copy(l), sCZSWAP(q1, q2)), apply_right_slow!(l, sCZSWAP(q1, q2)))
76+
# # @test isequal(apply_right!(copy(l), sCXSWAP(q1, q2)), apply_right_slow!(l, sCXSWAP(q1, q2)))
77+
# @test isequal(apply_right!(copy(l), sCNOT(q1, q2)), apply_right_slow!(l, sCNOT(q1, q2)))
78+
# # @test isequal(apply_right!(copy(l), sCPHASE(q1, q2)), apply_right_slow!(l, sCPHASE(q1, q2)))
79+
# @test isequal(apply_right!(copy(l), sZCX(q1, q2)), apply_right_slow!(l, sZCX(q1, q2)))
80+
# @test isequal(apply_right!(copy(l), sZCY(q1, q2)), apply_right_slow!(l, sZCY(q1, q2)))
81+
# @test isequal(apply_right!(copy(l), sZCZ(q1, q2)), apply_right_slow!(l, sZCZ(q1, q2)))
82+
# @test isequal(apply_right!(copy(l), sXCX(q1, q2)), apply_right_slow!(l, sXCX(q1, q2)))
83+
# @test isequal(apply_right!(copy(l), sXCY(q1, q2)), apply_right_slow!(l, sXCY(q1, q2)))
84+
# @test isequal(apply_right!(copy(l), sXCZ(q1, q2)), apply_right_slow!(l, sXCZ(q1, q2)))
85+
# @test isequal(apply_right!(copy(l), sYCX(q1, q2)), apply_right_slow!(l, sYCX(q1, q2)))
86+
# @test isequal(apply_right!(copy(l), sYCY(q1, q2)), apply_right_slow!(l, sYCY(q1, q2)))
87+
# @test isequal(apply_right!(copy(l), sYCZ(q1, q2)), apply_right_slow!(l, sYCZ(q1, q2)))
88+
# # @test isequal(apply_right!(copy(l), sZCrY(q1, q2)), apply_right_slow!(l, sZCrY(q1, q2)))
89+
# # @test isequal(apply_right!(copy(l), sInvZCrY(q1, q2)), apply_right_slow!(l, sInvZCrY(q1, q2)))
90+
# @test isequal(apply_right!(copy(l), sSQRTZZ(q1, q2)), apply_right_slow!(l, sSQRTZZ(q1, q2)))
91+
# @test isequal(apply_right!(copy(l), sInvSQRTZZ(q1, q2)), apply_right_slow!(l, sInvSQRTZZ(q1, q2)))
92+
# @test isequal(apply_right!(copy(l), sSQRTXX(q1, q2)), apply_right_slow!(l, sSQRTXX(q1, q2)))
93+
# @test isequal(apply_right!(copy(l), sInvSQRTXX(q1, q2)), apply_right_slow!(l, sInvSQRTXX(q1, q2)))
94+
# @test isequal(apply_right!(copy(l), sSQRTYY(q1, q2)), apply_right_slow!(l, sSQRTYY(q1, q2)))
95+
# @test isequal(apply_right!(copy(l), sInvSQRTYY(q1, q2)), apply_right_slow!(l, sInvSQRTYY(q1, q2)))
96+
# end
97+
# end
98+
end

0 commit comments

Comments
 (0)