qml.qchem.givens_decomposition¶
-
givens_decomposition
(unitary)[source]¶ Decompose a unitary into a sequence of Givens rotation gates with phase shifts and a diagonal phase matrix.
This decomposition is based on the construction scheme given in Optica, 3, 1460 (2016), which allows one to write any unitary matrix \(U\) as:
\[U = D \left(\prod_{(m, n) \in G} T_{m, n}(\theta, \phi)\right),\]where \(D\) is a diagonal phase matrix, \(T(\theta, \phi)\) is the Givens rotation gates with phase shifts and \(G\) defines the specific ordered sequence of the Givens rotation gates acting on wires \((m, n)\). The unitary for the \(T(\theta, \phi)\) gates appearing in the decomposition is of the following form:
\[\begin{split}T(\theta, \phi) = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & e^{i \phi} \cos(\theta) & -\sin(\theta) & 0 \\ 0 & e^{i \phi} \sin(\theta) & \cos(\theta) & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix},\end{split}\]where \(\theta \in [0, \pi/2]\) is the angle of rotation in the \(\{|01\rangle, |10\rangle \}\) subspace and \(\phi \in [0, 2 \pi]\) represents the phase shift at the first wire.
Example
unitary = np.array([[ 0.73678+0.27511j, -0.5095 +0.10704j, -0.06847+0.32515j], [-0.21271+0.34938j, -0.38853+0.36497j, 0.61467-0.41317j], [ 0.41356-0.20765j, -0.00651-0.66689j, 0.32839-0.48293j]]) phase_mat, ordered_rotations = givens_decomposition(unitary)
>>> phase_mat tensor([-0.20604358+0.9785369j , -0.82993272+0.55786114j, 0.56230612-0.82692833j], requires_grad=True) >>> ordered_rotations [(tensor([[-0.65087861-0.63937521j, -0.40933651-0.j ], [-0.29201359-0.28685265j, 0.91238348-0.j ]], requires_grad=True), (0, 1)), (tensor([[ 0.47970366-0.33308926j, -0.8117487 -0.j ], [ 0.66677093-0.46298215j, 0.5840069 -0.j ]], requires_grad=True), (1, 2)), (tensor([[ 0.36147547+0.73779454j, -0.57008306-0.j ], [ 0.2508207 +0.51194108j, 0.82158706-0.j ]], requires_grad=True), (0, 1))]
- Parameters
unitary (tensor) – unitary matrix on which decomposition will be performed
- Returns
diagonal elements of the phase matrix \(D\) and Givens rotation matrix \(T\) with their indices.
- Return type
(np.ndarray, list[(np.ndarray, tuple)])
- Raises
ValueError – if the provided matrix is not square.
Theory and Pseudocode
Givens Rotation
Applying the Givens rotation \(T(\theta, \phi)\) performs the following transformation of the basis states:
\[\begin{split}&|00\rangle \mapsto |00\rangle\\ &|01\rangle \mapsto e^{i \phi} \cos(\theta) |01\rangle - \sin(\theta) |10\rangle\\ &|10\rangle \mapsto e^{i \phi} \sin(\theta) |01\rangle + \cos(\theta) |10\rangle\\ &|11\rangle \mapsto |11\rangle.\end{split}\]Pseudocode
The algorithm that implements the decomposition is the following:
def givens_decomposition(U): for i in range(1, N): if i % 2: for j in range(0, i): # Find T^-1(i-j, i-j+1) matrix that nulls element (N-j, i-j) of U # Update U = U @ T^-1(i-j, i-j+1) else: for j in range(1, i): # Find T(N+j-i-1, N+j-i) matrix that nulls element (N+j-i, j) of U # Update U = T(N+j-i-1, N+j-i) @ U