PennyLane
Install
Install
  1. Compilation/
  2. Diagonal unitary decomposition

Diagonal unitary decomposition

OverviewDetailsResources

Diagonal unitary operators appear in various compilation scenarios, most frequently in the context of unitary synthesis and state preparation.

To decompose a diagonal unitary operator (without auxiliary qubits), we may use a recursive decomposition into multiplexed R_Z gates, which is called SelectPauliRot in PennyLane. This is shown in [1], citing earlier work [2]:

Decomposition of a diagonal unitary operator into multiplexed rotations SelectPauliRot

Here, \Delta denotes a diagonal operator and the half-filled control nodes indicate that the R_Z rotations are controlled uniformly, or multiplexed. See the Select-U(2) compilation page for a decomposition of these multiplexers.

Inputs

  • Diagonal unitary with length N=2^n for n qubits.

Outputs

  • Circuit consisting of
    • n-1 multiplexed R_Z rotations (qml.SelectPauliRot), one each with k controls for 1\leq k\leq n-1,
    • 1 single-qubit R_Z rotation (qml.RZ), and
    • a global phase (qml.GlobalPhase).

Example

Consider a diagonal unitary operator acting on three qubits, consisting of some random phases:

import pennylane as qml
import numpy as np
n = 3
wires = list(range(n))
D = np.exp(1j * np.random.random(2**n))

@qml.qnode(qml.device("reference.qubit", wires=n))
def qnode():
    qml.Hadamard(0)
    qml.Hadamard(2)
    qml.DiagonalQubitUnitary(D, wires=wires)
    return qml.expval(qml.X(0))
>>> print(qml.draw(qnode, show_matrices=False)())
0: ──╭U(M0)─┤  <X>
1: ──├U(M0)─┤
2: ──╰U(M0)─┤

We can decompose the DiagonalQubitUnitary iteratively, which we can control via the max_expansion keyword argument of qml.decompose. In the first step, we obtain a SelectPauliRot gate with two controls and a two-qubit diagonal unitary operator:

gate_set = {"DiagonalQubitUnitary", "SelectPauliRot", "RZ", "GlobalPhase"}
dec_node = qml.transforms.decompose(qnode, gate_set=gate_set, max_expansion=1)
>>> print(qml.draw(dec_node, show_matrices=False)())
0: ──╭U(M0)─╭SelectPauliRot(M1)─┤  <X>
1: ──╰U(M0)─├SelectPauliRot(M1)─┤
2: ─────────╰SelectPauliRot(M1)─┤

In the next step, the two-qubit diagonal unitary operator is decomposed into a single-qubit diagonal unitary and a SelectPauliRot gate with one control:

dec_node = qml.transforms.decompose(qnode, gate_set=gate_set, max_expansion=2)
>>> print(qml.draw(dec_node, show_matrices=False)())
0: ──U(M0)─╭SelectPauliRot(M1)─╭SelectPauliRot(M2)─┤  <X>
1: ────────╰SelectPauliRot(M1)─├SelectPauliRot(M2)─┤
2: ────────────────────────────╰SelectPauliRot(M2)─┤

In the last step, the single-qubit diagonal unitary is broken up into a global phase and a qml.RZ gate:

dec_node = qml.transforms.decompose(qnode, gate_set=gate_set, max_expansion=3)
>>> print(qml.draw(dec_node, show_matrices=False)())
0: ──GlobalPhase(-0.42)──RZ(0.02)─╭SelectPauliRot(M0)─╭SelectPauliRot(M1)─┤  <X>
1: ───────────────────────────────╰SelectPauliRot(M0)─├SelectPauliRot(M1)─┤
2: ───────────────────────────────────────────────────╰SelectPauliRot(M1)─┤

Typical usage

This decomposition can be useful as part of a compilation routine that splits off diagonal operators to commute them through control/multiplexing structures. It is also used implicitly in MottonenStapePreparation, both in a version with qml.RY rotations to create the correct amplitudes, and as seen above with qml.RZ rotations to apply phases.

As a concrete example, Select operators with a single target qubit can be decomposed using arbitrary diagonal unitary operators; for details, see the Select-U(2) compilation page. In turn, this page will also show how to decompose SelectPauliRot obtained from the decomposition presented here.

If phase gradient resource states and additional auxiliary qubits are available, diagonal unitaries can instead be decomposed at the same cost as the largest multiplexed rotation above.

References

[1] "Synthesis of quantum logic circuits", Vivek Shende, Stephen Bullock, Igor Markov, quant-ph/0406176, 2004.

[2] "Smaller circuits for arbitrary n-qubit diagonal computations", Stephen S. Bullock, Igor L. Markov, quant-ph/0303039, 2003.

Cite this page

@misc{PennyLane-diagonal-unitary-decomp,
    title = "Diagonal unitary decomposition",
    author = "David Wierichs",
    year = "2025",
    howpublished = "\url{https://pennylane.ai/compilation/diagonal-unitary-decomp}"
}

Page author(s)

David Wierichs
David Wierichs

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.

PennyLane

PennyLane is a cross-platform Python library for quantum computing, quantum machine learning, and quantum chemistry. Built by researchers, for research. Created with ❤️ by Xanadu.

Research

  • Research
  • Performance
  • Hardware & Simulators
  • Demos
  • Quantum Compilation
  • Quantum Datasets

Education

  • Teach
  • Learn
  • Codebook
  • Coding Challenges
  • Videos
  • Glossary

Software

  • Install PennyLane
  • Features
  • Documentation
  • Catalyst Compilation Docs
  • Development Guide
  • API
  • GitHub
Stay updated with our newsletter

© Copyright 2025 | Xanadu | All rights reserved

TensorFlow, the TensorFlow logo and any related marks are trademarks of Google Inc.

Privacy Policy|Terms of Service|Cookie Policy|Code of Conduct