Implementing diagonal and block diagonal unitary matrices in quantum circuits

Hi! I would like to know how PennyLane implements arbitrary unitary matrices in quantum circuits. For an example, is there a way to expand UA in the below code to see how it is being implemented using single-qubit and two-qubit gates in a quantum circuit?

Also, is there an efficient way to implement diagonal/block diagonal unitary matrices in quantum circuits? Could you please point me towards relevant references as well.

Thanks a lot!

# Import libraries
import pennylane as qml
import numpy as np

# Unitary matrix
A = np.diag([1, 1, 2, 3]) / 4

# Block encoded matrix
UA = qml.BlockEncode(A, wires=[0, 1, 2])

# Print the block encoded matrix
print(qml.matrix(UA).round(2))

# Decompose the block encoded matrix
LCU = qml.pauli_decompose(qml.matrix(UA))
print(LCU)

Hi @Shehara , welcome to the Forum!

qml.pauli_decompose uses the Walsh-Hadamard transform. You can learn more here in the theory section of the docs.

Instead of using BlockEncode, you can use qml.DiagonalQubitUnitary as long as the dimension is a power of two.

Here’s a code example.

# Import libraries
import pennylane as qml
import numpy as np

# Create a device
dev = qml.device('default.qubit',wires=2)

# Create an array with the values for the diagonal unitary matrix
D = np.array([1, 1, 1, 1])

# Create a QNode
@qml.qnode(dev)
def circuitD(D):
  qml.DiagonalQubitUnitary(D, wires=[0,1])
  return qml.probs()

# Draw your circuit and print the output
qml.draw_mpl(circuitD)(D)
circuitD(D)

To compute the decomposition you can use the compute_decomposition method (see more in the docs).

Example code:

qml.DiagonalQubitUnitary.compute_decomposition(D, wires=[0, 1])

Note that this method isn’t available for BlockEncode.
Does this answer your questions?

I hope this helps!