Skip to content

Commit afacef3

Browse files
committed
improve allocations
1 parent 1ce289b commit afacef3

File tree

2 files changed

+74
-54
lines changed

2 files changed

+74
-54
lines changed

src/apply_right.jl

Lines changed: 62 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,16 @@ Clifford operation or Pauli product
66
julia> apply_right!(C"X Z", sHadamard(1))
77
X₁ ⟼ + Z
88
Z₁ ⟼ + X
9+
julia> apply_right!(C"Y Z", C"Z Y")
10+
X₁ ⟼ + Z
11+
Z₁ ⟼ - X
12+
julia> apply_right!(C"Y Z", P"X")
13+
X₁ ⟼ + Y
14+
Z₁ ⟼ - Z
15+
```
916
17+
Example: Build a bell state decoder
18+
```jldoctest
1019
julia> cliff = one(CliffordOperator, 2)
1120
X₁ ⟼ + X_
1221
X₂ ⟼ + _X
@@ -22,13 +31,9 @@ X₁ ⟼ + ZX
2231
X₂ ⟼ + _X
2332
Z₁ ⟼ + X_
2433
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
34+
julia> apply!(bell(), cliff)
35+
+ Z_
36+
+ _Z
3237
```
3338
3439
See also: [`apply!`](@ref), [`apply_inv!`](@ref)
@@ -57,21 +62,18 @@ end
5762
function apply_right!(l::CliffordOperator, r::CliffordOperator; phases=true)
5863
nqubits(l)==nqubits(r) || throw(DimensionMismatch("The two Clifford operators need to act on the same number of qubits."))
5964
l_tab = tab(l)
65+
l_tab_copy = copy(l_tab)
6066
r_tab = tab(r)
6167
threadlocal = l.buffer
62-
new_xzs = Vector{typeof(threadlocal)}(undef, length(l_tab))
6368
@inbounds for row_r in eachindex(r_tab)
6469
zero!(threadlocal)
65-
apply_right_row_kernel!(threadlocal, row_r, l_tab, r_tab, phases=phases)
66-
new_xzs[row_r] = copy(threadlocal)
67-
end
68-
@inbounds for row_l in eachindex(l_tab)
69-
l_tab[row_l] = new_xzs[row_l]
70+
apply_right_row_kernel!(threadlocal, l_tab, row_r, l_tab_copy, r_tab; phases)
7071
end
7172
l
7273
end
7374

74-
@inline function apply_right_row_kernel!(new_lrow, row, l_tab, r_tab; phases=true)
75+
"""helper for computing the right multiplication of a row of a Clifford operator with another Clifford operator."""
76+
@inline function apply_right_row_kernel!(new_lrow, l_tab, row, l_tab_copy, r_tab; phases=true)
7577
phases && (new_lrow.phase[] = r_tab.phases[row])
7678
n = nqubits(l_tab)
7779
for qubit in 1:n
@@ -80,12 +82,13 @@ end
8082
new_lrow.phase[] -= 0x1
8183
end
8284
if x
83-
mul_left!(new_lrow, l_tab, qubit, phases=Val(phases))
85+
mul_left!(new_lrow, l_tab_copy, qubit, phases=Val(phases))
8486
end
8587
if z
86-
mul_left!(new_lrow, l_tab, qubit+n, phases=Val(phases))
88+
mul_left!(new_lrow, l_tab_copy, qubit+n, phases=Val(phases))
8789
end
8890
end
91+
l_tab[row] = new_lrow
8992
new_lrow
9093
end
9194

@@ -100,13 +103,13 @@ function apply_right!(l::CliffordOperator, r::sHadamard)
100103
end
101104

102105
function apply_right!(l::CliffordOperator, r::sHadamardXY)
103-
l[r.q] = mul_right_ignore_anticommute!(l[r.q], l[nqubits(l)+r.q])
106+
mul_right_ignore_anticomm!(tab(l), r.q, nqubits(l)+r.q)
104107
apply_right!(l, sY(r.q))
105108
return l
106109
end
107110

108111
function apply_right!(l::CliffordOperator, r::sHadamardYZ)
109-
l[nqubits(l)+r.q] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q], l[r.q])
112+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q, r.q)
110113
apply_right!(l, sZ(r.q))
111114
return l
112115
end
@@ -118,7 +121,7 @@ function apply_right!(l::CliffordOperator, r::sPhase)
118121
end
119122

120123
function apply_right!(l::CliffordOperator, r::sInvPhase)
121-
l[r.q] = mul_right_ignore_anticommute!(l[r.q], l[nqubits(l)+r.q])
124+
mul_right_ignore_anticomm!(tab(l), r.q, nqubits(l)+r.q)
122125
return l
123126
end
124127

@@ -145,7 +148,7 @@ function apply_right!(l::CliffordOperator, r::sSQRTX)
145148
end
146149

147150
function apply_right!(l::CliffordOperator, r::sInvSQRTX)
148-
l[nqubits(l)+r.q] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q], l[r.q])
151+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q, r.q)
149152
return l
150153
end
151154

@@ -163,13 +166,13 @@ end
163166

164167
function apply_right!(l::CliffordOperator, r::sCXYZ)
165168
rowswap!(tab(l), r.q, nqubits(l)+r.q)
166-
l[r.q] = mul_right_ignore_anticommute!(l[r.q], l[nqubits(l)+r.q])
169+
mul_right_ignore_anticomm!(tab(l), r.q, nqubits(l)+r.q)
167170
return l
168171
end
169172

170173
function apply_right!(l::CliffordOperator, r::sCZYX)
171174
rowswap!(tab(l), r.q, nqubits(l)+r.q)
172-
l[nqubits(l)+r.q] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q], l[r.q])
175+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q, r.q)
173176
apply_right!(l, sX(r.q))
174177
return l
175178
end
@@ -239,8 +242,8 @@ function apply_right!(l::CliffordOperator, r::sCPHASE)
239242
end
240243

241244
function apply_right!(l::CliffordOperator, r::sZCX)
242-
l[nqubits(l)+r.q2] = mul_right!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1]; phases=Val(true))
243-
l[r.q1] = mul_right!(l[r.q1], l[r.q2]; phases=Val(true))
245+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q2, nqubits(l)+r.q1)
246+
mul_right_ignore_anticomm!(tab(l), r.q1, r.q2)
244247
return l
245248
end
246249

@@ -252,14 +255,14 @@ function apply_right!(l::CliffordOperator, r::sZCY)
252255
end
253256

254257
function apply_right!(l::CliffordOperator, r::sZCZ)
255-
l[r.q2] = mul_right!(l[r.q2], l[nqubits(l)+r.q1]; phases=Val(true))
256-
l[r.q1] = mul_right!(l[r.q1], l[nqubits(l)+r.q2]; phases=Val(true))
258+
mul_right_ignore_anticomm!(tab(l), r.q2, nqubits(l)+r.q1)
259+
mul_right_ignore_anticomm!(tab(l), r.q1, nqubits(l)+r.q2)
257260
return l
258261
end
259262

260263
function apply_right!(l::CliffordOperator, r::sXCX)
261-
l[nqubits(l)+r.q2] = mul_right!(l[nqubits(l)+r.q2], l[r.q1]; phases=Val(true))
262-
l[nqubits(l)+r.q1] = mul_right!(l[nqubits(l)+r.q1], l[r.q2]; phases=Val(true))
264+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q2, r.q1)
265+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q1, r.q2)
263266
return l
264267
end
265268

@@ -292,18 +295,18 @@ function apply_right!(l::CliffordOperator, r::sYCZ)
292295
end
293296

294297
function apply_right!(l::CliffordOperator, r::sZCrY)
295-
l[r.q1] = mul_left!(l[r.q1], l[r.q2])
296-
l[r.q2] = mul_left!(l[r.q2], l[nqubits(l)+r.q1])
297-
l[nqubits(l)+r.q2] = mul_left!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1])
298-
l[r.q1] = mul_left!(l[r.q1], l[nqubits(l)+r.q2])
298+
mul_right_ignore_anticomm!(tab(l), r.q1, r.q2)
299+
mul_right_ignore_anticomm!(tab(l), r.q2, nqubits(l)+r.q1)
300+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q2, nqubits(l)+r.q1)
301+
mul_right_ignore_anticomm!(tab(l), r.q1, nqubits(l)+r.q2)
299302
return l
300303
end
301304

302305
function apply_right!(l::CliffordOperator, r::sInvZCrY)
303-
l[r.q1] = mul_left!(l[r.q1], l[r.q2])
304-
l[r.q2] = mul_left!(l[r.q2], l[nqubits(l)+r.q1])
305-
l[nqubits(l)+r.q2] = mul_left!(l[nqubits(l)+r.q2], l[nqubits(l)+r.q1])
306-
l[r.q1] = mul_left!(l[r.q1], l[nqubits(l)+r.q2])
306+
mul_right_ignore_anticomm!(tab(l), r.q1, r.q2)
307+
mul_right_ignore_anticomm!(tab(l), r.q2, nqubits(l)+r.q1)
308+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q2, nqubits(l)+r.q1)
309+
mul_right_ignore_anticomm!(tab(l), r.q1, nqubits(l)+r.q2)
307310
phases(l)[r.q1] ⊻= 0x02
308311
return l
309312
end
@@ -316,10 +319,10 @@ function apply_right!(l::CliffordOperator, r::sSQRTZZ)
316319
end
317320

318321
function apply_right!(l::CliffordOperator, r::sInvSQRTZZ)
319-
l[r.q1] = mul_right_ignore_anticommute!(l[r.q1], l[nqubits(l)+r.q1])
320-
l[r.q1] = mul_right_ignore_anticommute!(l[r.q1], l[nqubits(l)+r.q2])
321-
l[r.q2] = mul_right_ignore_anticommute!(l[r.q2], l[nqubits(l)+r.q1])
322-
l[r.q2] = mul_right_ignore_anticommute!(l[r.q2], l[nqubits(l)+r.q2])
322+
mul_right_ignore_anticomm!(tab(l), r.q1, nqubits(l)+r.q1)
323+
mul_right_ignore_anticomm!(tab(l), r.q1, nqubits(l)+r.q2)
324+
mul_right_ignore_anticomm!(tab(l), r.q2, nqubits(l)+r.q1)
325+
mul_right_ignore_anticomm!(tab(l), r.q2, nqubits(l)+r.q2)
323326
return l
324327
end
325328

@@ -331,10 +334,10 @@ function apply_right!(l::CliffordOperator, r::sSQRTXX)
331334
end
332335

333336
function apply_right!(l::CliffordOperator, r::sInvSQRTXX)
334-
l[nqubits(l)+r.q1] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q1], l[r.q1])
335-
l[nqubits(l)+r.q1] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q1], l[r.q2])
336-
l[nqubits(l)+r.q2] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q2], l[r.q1])
337-
l[nqubits(l)+r.q2] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q2], l[r.q2])
337+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q1, r.q1)
338+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q1, r.q2)
339+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q2, r.q1)
340+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q2, r.q2)
338341
return l
339342
end
340343

@@ -346,12 +349,12 @@ function apply_right!(l::CliffordOperator, r::sSQRTYY)
346349
end
347350

348351
function apply_right!(l::CliffordOperator, r::sInvSQRTYY)
349-
l[r.q1] = mul_right_ignore_anticommute!(l[r.q1], l[nqubits(l)+r.q1])
350-
l[nqubits(l)+r.q1] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q1], l[nqubits(l)+r.q2])
351-
l[nqubits(l)+r.q1] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q1], l[r.q2])
352-
l[r.q2] = mul_right_ignore_anticommute!(l[r.q2], l[r.q1])
353-
l[nqubits(l)+r.q2] = mul_right_ignore_anticommute!(l[nqubits(l)+r.q2], l[r.q1])
354-
l[r.q1] = mul_right_ignore_anticommute!(l[r.q1], l[nqubits(l)+r.q1])
352+
mul_right_ignore_anticomm!(tab(l), r.q1, nqubits(l)+r.q1)
353+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q1, nqubits(l)+r.q2)
354+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q1, r.q2)
355+
mul_right_ignore_anticomm!(tab(l), r.q2, r.q1)
356+
mul_right_ignore_anticomm!(tab(l), nqubits(l)+r.q2, r.q1)
357+
mul_right_ignore_anticomm!(tab(l), r.q1, nqubits(l)+r.q1)
355358
rowswap!(tab(l), r.q1, nqubits(l)+r.q1)
356359
rowswap!(tab(l), r.q2, nqubits(l)+r.q2)
357360
apply_right!(l, sZ(r.q2))
@@ -361,8 +364,13 @@ end
361364

362365
"""Multiply Pauli operators `l * r`, ignoring anticommutation phases (keeping only ±1, not ±i).
363366
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
367+
@inline function mul_right_ignore_anticomm!(s::Tableau, m, t::Tableau, i; phases::Val{B}=Val(true)) where B
368+
extra_phase = mul_right!((@view s.xzs[:,m]), (@view t.xzs[:,i]); phases=phases)
369+
B && (s.phases[m] = (extra_phase+s.phases[m]+s.phases[i])&0x2)
370+
s
371+
end
372+
@inline function mul_right_ignore_anticomm!(s::Tableau, m, i; phases::Val{B}=Val(true)) where B
373+
extra_phase = mul_right!((@view s.xzs[:,m]), (@view s.xzs[:,i]); phases=phases)
374+
B && (s.phases[m] = (extra_phase+s.phases[m]+s.phases[i])&0x2)
375+
s
368376
end

src/mul_leftright.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,18 @@ end
180180
s
181181
end
182182

183+
@inline function mul_right!(s::Tableau, m, t::Tableau, i; phases::Val{B}=Val(true)) where B
184+
extra_phase = mul_right!((@view s.xzs[:,m]), (@view t.xzs[:,i]); phases=phases)
185+
B && (s.phases[m] = (extra_phase+s.phases[m]+s.phases[i])&0x3)
186+
s
187+
end
188+
189+
@inline function mul_right!(s::Tableau, m, i; phases::Val{B}=Val(true)) where B
190+
extra_phase = mul_right!((@view s.xzs[:,m]), (@view s.xzs[:,i]); phases=phases)
191+
B && (s.phases[m] = (extra_phase+s.phases[m]+s.phases[i])&0x3)
192+
s
193+
end
194+
183195
@inline function mul_left!(s::Stabilizer, m, i; phases::Val{B}=Val(true)) where B
184196
mul_left!(tab(s), m, i; phases)
185197
end

0 commit comments

Comments
 (0)