@@ -19,19 +19,66 @@ function expand_circuit(circuit::Vector{<:AbstractOperation})
1919end
2020
2121
22- # SLOW versions of prepend! and prepend_inv! for CliffordOperator
2322""" the `prepend!` function is used to prepend any quantum operation to unitary Clifford operations"""
2423function prepend! end
25- function prepend! (l:: CliffordOperator , r:: AbstractCliffordOperator ; phases= false )
26- apply! (CliffordOperator (r, nqubits (l)), l; phases= phases)
27- end
28-
2924""" the prepend_inv! function is used to prepend the inverse of a quantum operation to unitary Clifford operations"""
3025function prepend_inv! end
31- function prepend_inv! (l:: CliffordOperator , r:: AbstractCliffordOperator ; phases= false )
32- apply! (inv (CliffordOperator (r, nqubits (l))), l; phases= phases)
26+
27+ # # SLOW versions of prepend! and prepend_inv! for CliffordOperator
28+ # function prepend!(l::CliffordOperator, r::AbstractCliffordOperator; phases=false)
29+ # apply!(CliffordOperator(r, nqubits(l)), l; phases=phases)
30+ # end
31+ # function prepend_inv!(l::CliffordOperator, r::AbstractCliffordOperator; phases=false)
32+ # apply!(inv(CliffordOperator(r, nqubits(l))), l; phases=phases)
33+ # end
34+
35+
36+ # FAST versions of prepend! and prepend_inv! for CliffordOperator - TODO
37+ prepend! (l:: CliffordOperator , r; phases) = prepend! (l, CliffordOperator (r, nqubits (l)); phases= phases)
38+
39+ function prepend! (l:: CliffordOperator , r:: CliffordOperator ; phases= false )
40+ nqubits (l)== nqubits (r) || throw (DimensionMismatch (" The tableau and the Clifford operator need to act on the same number of qubits. Consider specifying an array of indices as a third argument to the `apply!` function to avoid this error." ))
41+ l_tab = tab (l)
42+ r_tab = tab (r)
43+ threadlocal = l. buffer
44+ new_xzs = Vector {typeof(threadlocal)} (undef, length (l_tab))
45+ @inbounds for row_r in eachindex (r_tab)
46+ zero! (threadlocal)
47+ prepend_row_kernel! (threadlocal, row_r, l_tab, r_tab, phases= phases)
48+ new_xzs[row_r] = copy (threadlocal)
49+ end
50+ @inbounds for row_l in eachindex (l_tab)
51+ l_tab[row_l] = new_xzs[row_l]
52+ end
53+ l
3354end
3455
56+ @inline function prepend_row_kernel! (new_lrow, row, l_tab, r_tab; phases= true )
57+ phases && (new_lrow. phase[] = r_tab. phases[row])
58+ n = nqubits (l_tab)
59+ for qubit in 1 : n
60+ x,z = r_tab[row,qubit]
61+ if phases&& x&& z
62+ new_lrow. phase[] -= 0x1
63+ end
64+ if x
65+ mul_left! (new_lrow, l_tab, qubit, phases= Val (phases))
66+ end
67+ if z
68+ mul_left! (new_lrow, l_tab, qubit+ n, phases= Val (phases))
69+ end
70+ end
71+ new_lrow
72+ end
73+
74+ function prepend_inv! (l:: CliffordOperator , r:: CliffordOperator ; phases= false )
75+ prepend! (l, inv (r); phases= phases)
76+ end
77+
78+ # SLOW
79+ function prepend_inv! (l:: CliffordOperator , r; phases= false )
80+ prepend! (l, inv (CliffordOperator (r, nqubits (l))); phases= phases)
81+ end
3582
3683"""
3784Simulates measurement results of a Clifford circuit acting on an `n`-qubit |0⟩^⊗n state using the stabilizer tableau backtracking method,
@@ -55,7 +102,7 @@ function backtrajectory(circuit0::Vector{<:AbstractOperation}, n::Int)
55102
56103 for op in circuit
57104 if op isa AbstractCliffordOperator
58- T = prepend_inv! (T, op; phases= true ) # VERY INEFFICIENT - need a fast prepend_inv!
105+ T = prepend_inv! (T, op; phases= true )
59106 elseif op isa sMZ
60107 pivot = 0
61108 for c in 1 : n
0 commit comments