qml.matrix¶
-
matrix
(op, wire_order=None)[source]¶ The matrix representation of an operation or quantum circuit.
- Parameters
op (Operator or QNode or QuantumTape or Callable) – A quantum operator or quantum circuit.
wire_order (Sequence[Any], optional) – Order of the wires in the quantum circuit. Defaults to the order in which the wires appear in the quantum function.
- Returns
If an operator is provided as input, the matrix is returned directly in the form of a tensor. Otherwise, the transformed circuit is returned as described in
qml.transform
. Executing this circuit will provide its matrix representation.- Return type
TensorLike or qnode (QNode) or quantum function (Callable) or tuple[List[QuantumTape], function]
Example
Given an instantiated operator,
qml.matrix
returns the matrix representation:>>> op = qml.RX(0.54, wires=0) >>> qml.matrix(op) [[0.9637709+0.j 0. -0.26673144j] [0. -0.26673144j 0.9637709+0.j ]]
It can also be used in a functional form:
>>> x = torch.tensor(0.6, requires_grad=True) >>> matrix_fn = qml.matrix(qml.RX) >>> matrix_fn(x, wires=0) tensor([[0.9553+0.0000j, 0.0000-0.2955j], [0.0000-0.2955j, 0.9553+0.0000j]], grad_fn=<AddBackward0>)
In its functional form, it is fully differentiable with respect to gate arguments:
>>> loss = torch.real(torch.trace(matrix_fn(x, wires=0))) >>> loss.backward() >>> x.grad tensor(-0.5910)
This operator transform can also be applied to QNodes, tapes, and quantum functions that contain multiple operations; see Usage Details below for more details.
Usage Details
qml.matrix
can also be used with QNodes, tapes, or quantum functions that contain multiple operations.Consider the following quantum function:
def circuit(theta): qml.RX(theta, wires=1) qml.PauliZ(wires=0)
We can use
qml.matrix
to generate a new function that returns the unitary matrix corresponding to the functioncircuit
:>>> matrix_fn = qml.matrix(circuit) >>> theta = np.pi / 4 >>> matrix_fn(theta) array([[ 0.92387953+0.j, 0.+0.j , 0.-0.38268343j, 0.+0.j], [ 0.+0.j, -0.92387953+0.j, 0.+0.j, 0. +0.38268343j], [ 0. -0.38268343j, 0.+0.j, 0.92387953+0.j, 0.+0.j], [ 0.+0.j, 0.+0.38268343j, 0.+0.j, -0.92387953+0.j]])
Note that since
wire_order
was not specified, the default order[1, 0]
forcircuit
was used, and the unitary matrix corresponds to the operation \(R_X(\theta)\otimes Z\). To obtain the matrix for \(Z\otimes R_X(\theta)\), specifywire_order=[0, 1]
in the function call:>>> matrix = qml.matrix(circuit, wire_order=[0, 1])
You can also get the unitary matrix for operations on a subspace of a larger Hilbert space. For example, with the same function
circuit
andwire_order=["a", 0, "b", 1]
you obtain the \(16\times 16\) matrix for the operation \(I\otimes Z\otimes I\otimes R_X(\theta)\).This unitary matrix can also be used in differentiable calculations. For example, consider the following cost function:
def circuit(theta): qml.RX(theta, wires=1) qml.PauliZ(wires=0) qml.CNOT(wires=[0, 1]) def cost(theta): matrix = qml.matrix(circuit)(theta) return np.real(np.trace(matrix))
Since this cost function returns a real scalar as a function of
theta
, we can differentiate it:>>> theta = np.array(0.3, requires_grad=True) >>> cost(theta) 1.9775421558720845 >>> qml.grad(cost)(theta) -0.14943813247359922