qml.labs.dla.khaneja_glaser_involution

khaneja_glaser_involution(op, wire=None)[source]

Khaneja-Glaser involution, which is a type-AIII() Cartan involution with p=q.

Parameters
  • op (Union[np.ndarray, PauliSentence, Operator]) – Input operator

  • wire (int) – Qubit wire on which to perform Khaneja-Glaser decomposition

Returns

Whether op should go to the even or odd subspace of the decomposition

Return type

bool

See also

cartan_decomp()

See Khaneja and Glaser (2000) for reference.

Example

Let us first perform a single Khaneja-Glaser decomposition of \(\mathfrak{g} = \mathfrak{su}(8)\), i.e. the Lie algebra of all Pauli words on 3 qubits.

>>> g = list(qml.pauli.pauli_group(3)) # u(8)
>>> g = g[1:] # remove identity
>>> g = [op.pauli_rep for op in g]

We perform the first iteration on the first qubit. We use cartan_decomp().

>>> from functools import partial
>>> from pennylane.labs.dla import cartan_decomp, khaneja_glaser_involution
>>> k0, m0 = cartan_decomp(g, partial(khaneja_glaser_involution, wire=0))
>>> print(f"First iteration, AIII: {len(k0)}, {len(m0)}")
First iteration, AIII: 31, 32
>>> assert qml.labs.dla.check_cartan_decomp(k0, m0) # check Cartan commutation relations

We see that we split the 63-dimensional algebra \(\mathfrak{su}(8)\) into a 31-dimensional and a 32-dimensional subspace, and check_cartan_decomp() verified that they satisfy the commutation relations of a Cartan decomposition.

To expand on this example, we continue process recursively on the \(\mathfrak{k}_0\) subalgebra. Before we can apply the Khaneja-Glaser (type AIII) decomposition a second time, we need to a) remove the \(\mathfrak{u}(1)\) center from \(\mathfrak{k}_0=\mathfrak{su}(4)\oplus\mathfrak{su}(4)\oplus\mathfrak{u}(1)\) to make it semisimple and b) perform a different Cartan decomposition, which is sometimes termed class B.

>>> center_k0 = qml.center(k0, pauli=True) # Compute center of k0
>>> k0_semi = [op for op in k0 if op not in center_k0] # Remove center from k0
>>> print(f"Removed operators {center_k0}, new length: {len(k0_semi)}")
Removed operators [1.0 * Z(0)], new length: 30
>>> from pennylane.labs.dla import ClassB
>>> k1, m1 = cartan_decomp(k0_semi, partial(ClassB, wire=0))
>>> assert qml.labs.dla.check_cartan_decomp(k1, m1)
>>> print(f"First iteration, class B: {len(k1)}, {len(m1)}")
First iteration, class B: 15, 15

Now we arrived at the subalgebra \(\mathfrak{k}_1=\mathfrak{su}(4)\) and can perform the next iteration of the recursive decomposition.

>>> k2, m2 = cartan_decomp(k1, partial(khaneja_glaser_involution, wire=1))
>>> assert qml.labs.dla.check_cartan_decomp(k2, m2)
>>> print(f"Second iteration, AIII: {len(k2)}, {len(m2)}")
Second iteration, AIII: 7, 8

We can follow up on this by removing the center from \(\mathfrak{k}_1\) again, and applying a final class B decomposition:

>>> center_k2 = qml.center(k2, pauli=True)
>>> k2_semi = [op for op in k2 if op not in center_k2]
>>> print(f"Removed operators {center_k2}, new length: {len(k2_semi)}")
Removed operators [1.0 * Z(1)], new length: 6
>>> k3, m3 = cartan_decomp(k2_semi, partial(ClassB, wire=1))
>>> assert qml.labs.dla.check_cartan_decomp(k3, m3)
>>> print(f"Second iteration, class B: {len(k3)}, {len(m3)}")
Second iteration, class B: 3, 3

This concludes our example of the Khaneja-Glaser recursive decomposition, as we arrived at easy to implement single-qubit operations.