- Compilation/
One-qubit Synthesis
One-qubit Synthesis
One-qubit gate synthesis takes a 2 \times 2 unitary matrix U and synthesizes a circuit
composed of three (Pauli) rotation gates, with the first and third rotation often being performed
about the same axis, as in R_A(\omega)R_B(\theta)R_A(\phi). This pass is implemented as
qml.ops.one_qubit_decomposition
in PennyLane, and the rotation sequences ZYZ
, ZXZ
, XZX
and XYX
are supported
out of the box.
Inputs
- Unitary matrix U \in \mathbb{C}^{2\times 2}, U^\dagger U=\mathbb{I}.
- Rotation axis sequence, often in the form ABA with A,B being Pauli operators.
Outputs
- Decomposed circuit of the form R_A(\omega)R_B(\theta)R_A(\phi).
Arbitrary rotation axes
In principle, one-qubit synthesis works with any pair of rotation axes \vec{n}_{0},\vec{n}_1\in\mathbb{R}^3 with \|\vec{n}_j\|_2=1 (see Exercise 4.11 in [1]), also see the details tab. However, it is more common to work with Pauli rotation gates, which correspond to canonical basis vectors for the \vec{n}_j (see for example Theorem 4.1 and Exercise 4.10 in [1]).
Value-dependent output
Usually, the output circuit format is fixed once the rotation axes have been chosen. However, depending on the matrix entries of the input U, the structure can be reduced to fewer than three rotations. Note that this requires value-dependent, or conditional, compilation and happens almost never (in the mathematical sense) for a Haar-random 2\times 2 unitary matrix.
Example
Let us start with some unstructured special unitary matrix U (that is, a unitary matrix with unit
determinant) that we decompose into an R_Z R_Y R_Z
single-qubit circuit using qml.ops.one_qubit_decomposition
.
import pennylane as qml import numpy as np U = np.array([[0.485j, 0.856+0.179j], [-0.856+0.179j, -0.485j]]) assert np.allclose(U @ U.conj().T, np.eye(2)) assert np.isclose(np.linalg.det(U), 1.) ops_zyz = qml.ops.one_qubit_decomposition(U, wire=0) # rotations kwarg is "ZYZ" by default circ_zyz = qml.tape.QuantumScript(ops_zyz) assert np.allclose(U, qml.matrix(circ_zyz))
>>> print(qml.drawer.tape_text(circ_zyz, decimals=2)) 0: ──RZ(8.06)──RY(2.13)──RZ(1.36)─┤
We may use different rotation axes. For example, decomposing into an R_XR_ZR_X circuit instead:
ops_xzx = qml.ops.one_qubit_decomposition(U, wire=0, rotations="XZX") circ_xzx = qml.tape.QuantumScript(ops_xzx) assert np.allclose(U, qml.matrix(circ_xzx))
>>> print(qml.drawer.tape_text(circ_xzx, decimals=2)) 0: ──RX(8.91)──RZ(2.78)──RX(0.52)─┤
So far, we have not accounted for global phases, because the determinant of U
was 1
.
If an input unitary V has determinant \mathrm{det}(V)=e^{-i\varphi} instead (note that it must be
a complex number with |\mathrm{det}(V)|^2=1 because of unitarity), one_qubit_decomposition
allows us to extract this as well:
phi = 0.521 V = U * np.exp(-1j * phi) # non-special unitary ops_with_phase = qml.ops.one_qubit_decomposition(V, wire=0, return_global_phase=True) circ_with_phase = qml.tape.QuantumScript(ops_with_phase) assert np.allclose(V, qml.matrix(circ_with_phase)) assert np.isclose(ops_with_phase[-1].data[0], phi) # Extracted global phase matches phi
>>> print(qml.drawer.tape_text(circ_with_phase, decimals=2)) 0: ──RZ(8.06)──RY(2.13)──RZ(1.36)──GlobalPhase(-0.52)─┤
Note how the global phase is separated out as its own operation and the rotation angles have not changed.
While no one-qubit circuit takes more than three rotations, there are simple rotations
about one of the Pauli words that could be compiled into only one rotation. Similarly, products of
two rotations would also not require all three rotations in the generic compilation.
For such rotations, one or two gates can be skipped, provided that the rotation axis/axes of the
original operators is/are among the axes into which we are compiling.
This is a value-dependent optimization of one_qubit_decomposition
, which is usually not applied
automatically in PennyLane.
Typical usage
This pass is typically used in one of two scenarios: first, if a one-qubit operator to be
applied is given in terms of a unitary matrix rather than a gate decomposition. Second, if
a sequence of more than three (parametrized) single-qubit rotations occurs in a circuit, we know
that computing their matrix and applying one_qubit_decomposition
will reduce the sequence
to at most three rotation gates.
In addition, one-qubit (re)synthesis is used as a subroutine, for example in
two-qubit synthesis.
Finally, the fact that any arbitrary sequence of single-qubit operators can be condensed into a sequence of three rotations is heavily used in compilation. As it bounds the number of degrees of freedom that can be realized on a single qubit before applying entangling operators to it, it is also very useful in obtaining gate counts and proving circuit complexity statements; see for example Prop. III.1 in Shende et al. (2004).
References
[1] "Quantum computation and quantum information", Michael A. Nielsen, Isaac L. Chuang, Cambridge Press, 2010, DOI:10.1017/CBO9780511976667
Cite this page
@misc{PennyLane-1QSynthesis, title={One-qubit Synthesis}, howpublished={\url{https://pennylane.ai/compilation/one-qubit-synthesis}}, year={2025} }
Page author(s)
David Wierichs
I like to think about differentiation and representations of quantum programs, and I enjoy coding up research ideas and useful features for anyone to use in PennyLane.