qml.operation.expand_matrix

expand_matrix(base_matrix, wires, wire_order=None)[source]

Re-express a base matrix acting on a subspace defined by a set of wire labels according to a global wire order.

Parameters
  • base_matrix (tensor_like) – base matrix to expand

  • wires (Iterable) – wires determining the subspace that base matrix acts on; a base matrix of dimension \(2^n\) acts on a subspace of \(n\) wires

  • wire_order (Iterable) – global wire order, which has to contain all wire labels in wires, but can also contain additional labels

Returns

expanded matrix

Return type

tensor_like

Example

If the wire order is identical to wires, the original matrix gets returned:

>>> base_matrix = np.array([[1, 2, 3, 4],
...                         [5, 6, 7, 8],
...                         [9, 10, 11, 12],
...                         [13, 14, 15, 16]])
>>> print(expand_matrix(base_matrix, wires=[0, 2], wire_order=[0, 2]))
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]
 [13 14 15 16]]

If the wire order is a permutation of wires, the entries of the base matrix get permuted:

>>> print(expand_matrix(base_matrix, wires=[0, 2], wire_order=[2, 0]))
[[ 1  3  2  4]
 [ 9 11 10 12]
 [ 5  7  6  8]
 [13 15 14 16]]

If the wire order contains wire labels not found in wires, the matrix gets expanded:

>>> print(expand_matrix(base_matrix, wires=[0, 2], wire_order=[0, 1, 2]))
[[ 1  2  0  0  3  4  0  0]
 [ 5  6  0  0  7  8  0  0]
 [ 0  0  1  2  0  0  3  4]
 [ 0  0  5  6  0  0  7  8]
 [ 9 10  0  0 11 12  0  0]
 [13 14  0  0 15 16  0  0]
 [ 0  0  9 10  0  0 11 12]
 [ 0  0 13 14  0  0 15 16]]

The method works with tensors from all autodifferentiation frameworks, for example:

>>> base_matrix_torch = torch.tensor([[1., 2.],
...                                   [3., 4.]], requires_grad=True)
>>> res = expand_matrix(base_matrix_torch, wires=["b"], wire_order=["a", "b"])
>>> type(res)
torch.Tensor
>>> res.requires_grad
True
>>> print(expand_matrix(base_matrix, wires=[0, 2]))
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]
 [13 14 15 16]]