# qml.transforms.unitary_to_rot¶

unitary_to_rot(tape)[source]

Quantum function transform to decomposes all instances of single-qubit and select instances of two-qubit QubitUnitary operations to parametrized single-qubit operations.

For single-qubit gates, diagonal operations will be converted to a single RZ gate, while non-diagonal operations will be converted to a Rot gate that implements the original operation up to a global phase. Two-qubit gates will be decomposed according to the pennylane.transforms.two_qubit_decomposition() function.

Warning

This transform is not fully differentiable for 2-qubit QubitUnitary operations. See usage details below.

Parameters

qfunc (function) – a quantum function

Example

Suppose we would like to apply the following unitary operation:

U = np.array([
[-0.17111489+0.58564875j, -0.69352236-0.38309524j],
[ 0.25053735+0.75164238j,  0.60700543-0.06171855j]
])


The unitary_to_rot transform enables us to decompose such numerical operations while preserving differentiability.

def qfunc():
qml.QubitUnitary(U, wires=0)
return qml.expval(qml.PauliZ(0))


The original circuit is:

>>> dev = qml.device('default.qubit', wires=1)
>>> qnode = qml.QNode(qfunc, dev)
>>> print(qml.draw(qnode)())
0: ──U(M0)─┤  <Z>
M0 =
[[-0.17111489+0.58564875j -0.69352236-0.38309524j]
[ 0.25053735+0.75164238j  0.60700543-0.06171855j]]


We can use the transform to decompose the gate:

>>> transformed_qfunc = unitary_to_rot(qfunc)
>>> transformed_qnode = qml.QNode(transformed_qfunc, dev)
>>> print(qml.draw(transformed_qnode)())
0: ──Rot(-1.35,1.83,-0.61)─┤  <Z>


This decomposition is not fully differentiable. We can differentiate with respect to input QNode parameters when they are not used to explicitly construct a $$4 \times 4$$ unitary matrix being decomposed. So for example, the following will work:

U = scipy.stats.unitary_group.rvs(4)

def circuit(angles):
qml.QubitUnitary(U, wires=["a", "b"])
qml.RX(angles, wires="a")
qml.RY(angles, wires="b")
qml.CNOT(wires=["b", "a"])
return qml.expval(qml.PauliZ(wires="a"))

dev = qml.device('default.qubit', wires=["a", "b"])
transformed_qfunc = qml.transforms.unitary_to_rot(circuit)
transformed_qnode = qml.QNode(transformed_qfunc, dev)

>>> g = qml.grad(transformed_qnode)
>>> params = np.array([0.2, 0.3], requires_grad=True)
>>> g(params)
array([ 0.00296633, -0.29392145])


However, the following example will not be differentiable:

def circuit(angles):
z = angles
x = angles

Z_mat = np.array([[np.exp(-1j * z / 2), 0.0], [0.0, np.exp(1j * z / 2)]])

c = np.cos(x / 2)
s = np.sin(x / 2) * 1j
X_mat = np.array([[c, -s], [-s, c]])

U = np.kron(Z_mat, X_mat)