---
title: givens_decomposition (latest version)
description: API reference for qiskit_fermions.linalg.givens_decomposition in the latest version of qiskit-fermions
source: https://eu-de.quantum.cloud.ibm.com/docs/en/api/qiskit-fermions/linalg-givens-decomposition
---

# givens\_decomposition

`givens_decomposition(unitary)`

Decomposes a unitary matrix into Givens rotations and diagonal phases.

The $n \times n$ unitary matrix, $U$, can be decomposed into a diagonal matrix, $D$, and sequence of $2 \times 2$ Givens rotations, $G$, acting on adjacent indices. This algorithm   [\[1\]](#id2) requires at most $n (n-1) / 2$ such Givens rotations.

Each Givens rotation is defined by a 4-tuple, `(c, s, i, j)`, with:

- `c`: the real-valued cosine
- `s`: the complex-valued sine
- `i`: the first row index
- `j`: the second row index

which result in a matrix of the form:

$$
\begin{pmatrix}
c & s \\
-s^\dagger & c
\end{pmatrix}
$$

**Parameters**

**unitary** – the unitary matrix, $U$, to be decomposed.

**Returns**

A 2-tuple consisting of

- the sequence of Givens rotations represented as 4-tuples as explained above
- the vector of complex phases of the diagonal matrix, $D$

The original unitary is recovered by processing the returned rotations in reverse order and right-multiplying the diagonal matrix by the element-wise complex conjugate of each rotation matrix $G_k$ (as defined above). That is, for $N$ returned rotations,

$$
U = D \cdot \overline{G_N} \cdot \overline{G_{N-1}} \cdots \overline{G_1},
$$

where $\overline{G_k}$ denotes element-wise conjugation (not the conjugate transpose) and each $G_k$ acts only on rows/columns $i$ and $j$ of its rotation.

```pycon
>>> import numpy as np
>>> from qiskit_fermions.linalg import givens_decomposition
>>> unitary = np.array([[0.6, 0.8j], [0.8, -0.6j]], dtype=complex)
>>> rotations, phases = givens_decomposition(unitary)
>>> reconstructed = np.diag(phases).astype(complex)
>>> for c, s, i, j in rotations[::-1]:
...     givens_mat = np.eye(2, dtype=complex)
...     givens_mat[np.ix_((i, j), (i, j))] = [[c, s], [-s.conjugate(), c]]
...     reconstructed = reconstructed @ givens_mat.conj()
>>> bool(np.allclose(reconstructed, unitary))
True
```

\[[1](#id1)]

W. R. Clements et al., Optimal design for universal multiport interferometers, Optica 3, 1460-1465 (2016), [doi:10.1364/OPTICA.3.001460](https://doi.org/10.1364/OPTICA.3.001460).
