Pauli Basis and Clifford group
In this section, we introduce the definition of Pauli strings and basic operations on them. We also introduce the Clifford group and how to simulate a Clifford circuit applied on Pauli strings.
Pauli Strings
A pauli string is a tensor product of Pauli operators acting on different qubits. PauliString
is a subtype of [CompositeBlock
] with a field ids
storing the Pauli operators. We can define pauli string with PauliString
or paulistring
.
using TensorQEC, TensorQEC.Yao
PauliString(X, I2, Z, Y) # X_1Z_3Y_4
paulistring(4, X, (1, 2, 4)) # X_1X_2X_4
XXIX
We can use Yao.mat
to get the matrix representation of a Pauli string.
mat(ComplexF64, PauliString(X, Z)) # X_1Z_2
4×4 LuxurySparse.SDPermMatrix{ComplexF64, Int64, Vector{ComplexF64}, Vector{Int64}}:
0.0+0.0im 1.0+0.0im 0.0+0.0im 0.0+0.0im
1.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.0+0.0im -1.0+0.0im
0.0+0.0im 0.0+0.0im -1.0+0.0im 0.0+0.0im
Pauli Basis
pauli_basis
generates all the Pauli strings of a given length. Those Pauli strings are stored in a high-dimensional array.
pauli_basis(2)
4×4 Matrix{PauliString{2}}:
II IX IY IZ
XI XX XY XZ
YI YX YY YZ
ZI ZX ZY ZZ
pauli_decomposition
returns the coefficients of a matrix in the Pauli basis.
pauli_decomposition(ConstGate.CNOT)
4×4 Matrix{ComplexF64}:
0.5+0.0im 0.5+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
0.0+0.0im 0.0+0.0im 0.0+0.0im 0.0+0.0im
0.5+0.0im -0.5+0.0im 0.0+0.0im 0.0+0.0im
That implies that $CNOT = \frac{1}{2} (I \otimes I + I \otimes X + Z \otimes I - Z \otimes X)$. We can check this by
0.5*(mat(kron(I2,I2) + kron(I2,X) + kron(Z,I2) - kron(Z,X))) == mat(ConstGate.CNOT)
true
pauli_mapping
returns the matrix representation of a quantum gate in the Pauli basis. For Hadamard gate H, we know that $HIH = I, HXH = Z, HYH = -Y, HZH = X$. We can convert $H$ into the Pauli basis.
pauli_mapping(H)
4×4 Matrix{Float64}:
1.0 0.0 0.0 0.0
0.0 0.0 0.0 1.0
0.0 0.0 -1.0 0.0
0.0 1.0 0.0 0.0
Clifford Group
Clifford group can be generated by Hadamard gate, S gate and CNOT gate[Bravyi2022]. We can generate the Clifford group with clifford_group
.
clifford_group(1)
24-element Vector{LuxurySparse.PermMatrix{Int8, UInt8, StaticArraysCore.SVector{4, Int8}, StaticArraysCore.SVector{4, UInt8}}}:
[1 0 0 0; 0 0 0 1; 0 0 -1 0; 0 1 0 0]
[1 0 0 0; 0 0 1 0; 0 -1 0 0; 0 0 0 1]
[1 0 0 0; 0 1 0 0; 0 0 1 0; 0 0 0 1]
[1 0 0 0; 0 0 0 1; 0 1 0 0; 0 0 1 0]
[1 0 0 0; 0 0 -1 0; 0 0 0 -1; 0 1 0 0]
[1 0 0 0; 0 -1 0 0; 0 0 -1 0; 0 0 0 1]
[1 0 0 0; 0 1 0 0; 0 0 0 -1; 0 0 1 0]
[1 0 0 0; 0 1 0 0; 0 0 0 1; 0 0 -1 0]
[1 0 0 0; 0 0 0 1; 0 0 1 0; 0 -1 0 0]
[1 0 0 0; 0 0 1 0; 0 0 0 1; 0 1 0 0]
⋮
[1 0 0 0; 0 1 0 0; 0 0 -1 0; 0 0 0 -1]
[1 0 0 0; 0 0 1 0; 0 1 0 0; 0 0 0 -1]
[1 0 0 0; 0 -1 0 0; 0 0 0 1; 0 0 1 0]
[1 0 0 0; 0 -1 0 0; 0 0 0 -1; 0 0 -1 0]
[1 0 0 0; 0 0 0 -1; 0 0 -1 0; 0 -1 0 0]
[1 0 0 0; 0 0 -1 0; 0 -1 0 0; 0 0 0 -1]
[1 0 0 0; 0 0 -1 0; 0 0 0 1; 0 -1 0 0]
[1 0 0 0; 0 -1 0 0; 0 0 1 0; 0 0 0 -1]
[1 0 0 0; 0 0 0 -1; 0 1 0 0; 0 0 -1 0]
Each element in the Clifford group acts on pauli basis as a permutation matrix. For $n= 1, 2$, and $3$, this group contains $24$, $11520$, and $92897280$ elements, respectively. We can use to_perm_matrix
to convert a matrix into a permutation matrix.
pm = to_perm_matrix(H)
pm.perm, pm.vals
([1, 4, 3, 2], Int8[1, 1, -1, 1])
With the permutation matrix, we can apply a Clifford gate to a Pauli string by perm_of_paulistring
. Here we apply the Hadamard gate to the second qubit of Pauli string $I_1X_2$ and get $I_1Z_2$ with a phase $1$.
ps1 = PauliString(I2, X)
ps2, phase = perm_of_paulistring(ps1, [2]=>pm)
ps1, ps2, phase
(IX, IZ, 1)
Put those all together, we can apply a Clifford circuit to a Pauli string by clifford_simulate
.
qc = chain(put(5, 1 => H), control(5, 1, 2 => Z), control(5, 3, 4 => X), control(5, 5, 3 => X), put(5, 1 => X))
vizcircuit(qc)
Apply the circuit to Pauli string $Z_1Y_2I_3Y_4X_5$, we get $Y_1X_2Y_3Y_4Y_5$ with a phase $1$.
ps = PauliString(Z, Y, I2, Y, X)
ps2, phase = clifford_simulate(ps, qc)
(YXYYY, -1)
where ps2
is the Pauli string after the Clifford circuit and phase
is the phase factor. It corresponds to the following quantum circuit.
clifford_simulation_circuit = chain(qc', ps, qc)
CircuitStyles.barrier_for_chain[] = true # setup barrier for better visualization
vizcircuit(clifford_simulation_circuit)
We can check the result by
CircuitStyles.barrier_for_chain[] = false # disable barrier
phase * mat(clifford_simulation_circuit) ≈ mat(ps2)
true
This page was generated using Literate.jl.
- Bravyi2022Bravyi, S., Latone, J.A., Maslov, D., 2022. 6-qubit optimal Clifford circuits. npj Quantum Inf 8, 1–12. https://doi.org/10.1038/s41534-022-00583-7