- Compilation/
(Clifford + T) Gate Set
(Clifford + T) Gate Set
Decomposing R_Z rotations
One of the challenges in decomposing an arbitrary circuit into a Clifford + T circuit is decomposing the Pauli rotations.
A single-qubit Pauli rotation can always be written as a series of the Clifford operations S, Hadamard and T.
Let us confirm the (Clifford + T) realization of R_Z\left(\frac{\pi}{128}\right) from the overview in the following code example.
import pennylane as qml import numpy as np H = qml.matrix(qml.Hadamard(0)) S = qml.matrix(qml.S(0)) T = qml.matrix(qml.T(0)) from functools import reduce ops = eval(",".join("SHTHTHTHTHTHTHTSHTHTHTHTSHTHTHTHTHTSHTSHTHTHTHTHTSHTHTHTSHTSHTHTSHTSHTSHTHTHTHTSHTHTHTHTHTSHTSHTHTSHTHTSHTSHTSHTSHTHTSHTSHTSHTSHTHTHTSHTSHTSHTHTHTHTSHTHTSHTHTHTSHTHTHTHTSHTHTSHTHTSHTSHTSHTHTHTHTHTHTHTSHTHTSHTHTHTSHTSHTHTHTSHTSHTSHTHTSHTHTHTHTSHTSHTSHSSS")) op = reduce(lambda x, y: x @ y, ops[::-1]) np.allclose(qml.matrix(qml.RZ(np.pi/128, 0)) * np.exp(-1j*np.pi/4)**7, op, atol=1e-10) # True
Solovay-Kitaev algorithm
The Solovay-Kitaev algorithm lets us decompose an arbitrary single-qubit gate into Clifford and T gates [2]. It is implemented in PennyLane in the qml.ops.sk_decomposition.
For example, it recognizes a \pi/4 RZ
rotation as a T gate.
>>> op = qml.RZ(np.pi/4, 0) >>> qml.ops.sk_decomposition(op, 1e-10) [T(0), GlobalPhase(array(0.39269908), wires=[])]
A rotation around X by the same angle yields a T gate transformed by a Hadamard.
>>> op = qml.RX(np.pi/4, 0) >>> qml.ops.sk_decomposition(op, 1e-10) [H(0), T(0), H(0), GlobalPhase(array(0.39269908), wires=[])]
Similarly, we can also decompose arbitrary single-qubit gates. For the sake of brevity, we target a very low precision.
>>> import scipy >>> generator = np.random.RandomState(1).rand(2, 2) >>> op_gen = generator.T @ generator # make Hermitian >>> U = scipy.linalg.expm(-1j * op_gen) >>> op = qml.QubitUnitary(U, wires=[0]) >>> decomp = qml.ops.sk_decomposition(op, 1) >>> decomp [Adjoint(T(0)), H(0), Adjoint(T(0)), H(0), Adjoint(T(0)), H(0), Adjoint(T(0)), GlobalPhase(array(0.86479715), wires=[])] >>> matrix_sk = qml.prod(*reversed(decomp)).matrix() >>> qml.math.allclose(op.matrix(), matrix_sk, atol=1) True
Gridsynth algorithm
Gridsynth [3] is a more modern algorithm with better performance achieving the same goal of transforming arbitrary single-qubit operations into series of S, H and T gates [3]. It relies on the number-theoretic characterization of the single-qubit Clifford + T unitaries, which states that they have elements in the algebraic ring \mathbb{Z}\left[\frac{1}{\sqrt{2}}, i\right]. This allows one to approximate a unitary by rounding it off into the ring, leading to decompositions of much lower depth than previously possible.
(Clifford + T) decomposition
An arbitrary quantum circuit can be decomposed into (Clifford + T) gates using the qml.clifford_t_decomposition transform. The target Clifford gates are
Identity
,PauliX
,PauliY
,PauliZ
,SX
,S
, andHadamard
for single-qubit operations andCNOT
,CY
,CZ
,SWAP
, andISWAP
for two-qubit gates.
>>> @qml.transforms.clifford_t_decomposition ... def qfunc(): ... qml.Toffoli([0, 1, 2]) >>> print(qml.draw(qfunc)())
0: ───────────╭●───────────╭●────╭●─────╭●──T─┤ 1: ────╭●─────│─────╭●─────│───T─╰X──T†─╰X────┤ 2: ──H─╰X──T†─╰X──T─╰X──T†─╰X──T──H───────────┤