PennyLane
  • Why PennyLane
  • Getting Started
  • Documentation
  • Ecosystem
Install
Install
  1. Compilation/
  2. Two-qubit Synthesis

Two-qubit Synthesis

Two-qubit gate synthesis takes in a 4 \times 4 unitary matrix U and synthesizes a circuit with an optimal \text{CNOT} gate count. This pass is implemented as qml.ops.two_qubit_decomposition in PennyLane.

The resulting circuits can take one of the following four forms, depending on how many CNOT gates are necessary.

CNOTs0123
Circuit
 -A- 
-B-
-C--╭●--A-
-D--╰X--B-
-A--╭X--RZ(α)--╭X--C-
-B--╰●--RX(β)--╰●--D-
-C--╭X--RZ(δ)--╭●---------╭X--A-
-D--╰●--RY(β)--╰X--RY(α)--╰●--B-

A, B, C, D \in \text{SU}(2) are general single-qubit gates and, together with the angles \alpha, \beta, \delta \in \mathbb{R}, can be determined algebraically directly from the input matrix U (the exact process is described in the ).

In a NISQ setting, where costs for CNOT gates dominate, applying this pass to two-qubit gates may reduce the overall CNOT gate count.

Inputs

  • Unitary matrix U \in \mathbb{C}^{4\times 4}

Outputs

  • Decomposed circuit with an optimal \text{CNOT} gate count

Example

A tensor product of two operators require 0 CNOT gates.

import pennylane as qml import numpy as np U = qml.matrix(qml.exp(-1j * 0.5 * X(0)), wire_order=range(2)) U @= qml.matrix(qml.exp(-1j * 0.5 * Y(1)), wire_order=range(2)) ops = qml.ops.two_qubit_decomposition(U, range(2)) circ = qml.tape.QuantumScript(ops, []) assert np.allclose(U, qml.matrix(circ, wire_order=range(2))) print(qml.drawer.tape_text(circ))
0: ──RZ──RY──RZ─┤ 1: ──RZ──RY──RZ─┤

Note that a ZYZ decomposition is used to represent the \text{SU}(2) gate on each wire. This leads to a redundancy because the input matrix on wire 1 is already a R_Y rotation.

A general \text{SU}(4) element requires 3 CNOT gates.

SU4_generators = list(qml.pauli.pauli_group(2)) arbitrary_op = qml.dot(np.arange(16), SU4_generators) U = qml.matrix(qml.exp(-1j * arbitrary_op)) ops = qml.ops.two_qubit_decomposition(U, range(2)) circ = qml.tape.QuantumScript(ops, []) print(qml.drawer.tape_text(circ))
0: ──RZ──RY──RZ─╭X──RZ─╭●─────╭X──RZ──RY──RZ─┤ 1: ──RZ──RY──RZ─╰●──RY─╰X──RY─╰●──RZ──RY──RZ─┤

There are intermediate cases with 1 and 2 CNOTs, respectively. Here is an example where 2 CNOT gates are required.

U = qml.matrix(qml.exp(-1j * 0.5 * X(0) @ Y(1)), wire_order=range(2)) ops = qml.ops.two_qubit_decomposition(U, range(2)) circ = qml.tape.QuantumScript(ops, []) assert np.allclose(U, qml.matrix(circ, wire_order=range(2))) print(qml.drawer.tape_text(circ))
0: ──RZ──RY──RZ─╭X──RZ─╭X──RZ──RY──RZ─┤ 1: ──RZ──RY──RZ─╰●──RX─╰●──RZ──RY──RZ─┤

While the CNOT count is optimal, the overall decomposition may not be. This is because this pass always targets a fixed ansatz structure and may introduce some redundant single qubit gates, as illustrated by this example.

>>> def circ(): ... qml.CNOT((0, 1)) ... qml.RX(0.5, 0) ... qml.RY(0.5, 1) >>> U = qml.matrix(circ, wire_order=range(2))() >>> print("Input circuit:\n") >>> print(qml.draw(circ)(), "\n") Input circuit: 0: ─╭●──RX(0.50)─┤ 1: ─╰X──RY(0.50)─┤ >>> ops = qml.ops.two_qubit_decomposition(U, range(2)) >>> circ_re = qml.tape.QuantumScript(ops, []) >>> assert np.allclose(U, qml.matrix(circ_re, wire_order=range(2))) >>> print("Synthesized circuit:\n") >>> print(qml.drawer.tape_text(circ_re, decimals=2)) Synthesized circuit: 0: ──RZ(2.01)──RY(0.00)──RZ(9.44)─╭●──RZ(8.96)──RY(0.50)──RZ(11.00)─┤ 1: ──RZ(4.71)──RY(1.02)──RZ(1.57)─╰X──RZ(1.00)──RY(1.09)──RZ(11.28)─┤

Typical usage

This pass is necessary when the input unitary is provided as a matrix rather than a gate decomposition. In a NISQ setting, where costs for CNOT gates dominate, applying this pass to two-qubit gates may reduce the overall CNOT gate count.

References

[1] "Minimal Universal Two-qubit Quantum Circuits", Vivek V. Shende, Igor L. Markov, Stephen S. Bullock, arxiv:quant-ph/0308033, 2003

[2] "Recognizing Small-Circuit Structure in Two-Qubit Operators and Timing Hamiltonians to Compute Controlled-Not Gates", Vivek V. Shende, Stephen S. Bullock, Igor L. Markov, arXiv:quant-ph/0308045, 2003

[3] "Finding Small Two-Qubit Circuits", Vivek V. Shende, Igor L. Markov, and Stephen S. Bullock, preprint, 2004


Cite this page

@misc{PennyLane-2QSynthesis,
title={Two-qubit Synthesis},
howpublished={\url{https://pennylane.ai/compilation/two-qubit-synthesis}},
year={2025}
}

Page author(s)

Korbinian Kottmann
Korbinian Kottmann

Korbinian Kottmann

Quantum simulation & open source software

PennyLane

PennyLane is an open-source software framework for quantum machine learning, quantum chemistry, and quantum computing, with the ability to run on all hardware. Built with ❤️ by Xanadu.

Stay updated with our newsletter

For researchers

  • Research
  • Features
  • Demos
  • Compilation
  • Datasets
  • Performance
  • Learn
  • Videos
  • Documentation
  • Teach

For learners

  • Learn
  • Codebook
  • Teach
  • Videos
  • Challenges
  • Demos
  • Compilation
  • Glossary

For developers

  • Features
  • Documentation
  • API
  • GitHub
  • Datasets
  • Demos
  • Compilation
  • Performance
  • Devices
  • Catalyst

© 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