We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] qml.matrix(op) and op.matrix() are different for Barrier and WireCut
### Expected behavior

I expected them both to pass, or both to fail.

### Actual behavior

`qml.matrix(qml.Barrier(0))` passed, `qml.Barrier(0).matrix()` failed. Same for `qml.WireCut`.

### Additional information

Attached source code is for Barrier, but the same thing happens with WireCut.

### Source code

```shell
>>> import pennylane as qml
>>> op = qml.Barrier(0)
>>> qml.matrix(op)
array([[1.]])
>>> op.matrix()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/matthews/src/github.com/PennyLaneAI/pennylane/pennylane/operation.py", line 1405, in matrix
    canonical_matrix = self.compute_matrix(*self.parameters, **self.hyperparameters)
  File "/Users/matthews/src/github.com/PennyLaneAI/pennylane/pennylane/operation.py", line 446, in compute_matrix
    raise MatrixUndefinedError
pennylane.operation.MatrixUndefinedError
```


### Tracebacks

_No response_

### System information

```shell
Name: PennyLane
Version: 0.27.0
Summary: PennyLane is a Python quantum machine learning library by Xanadu Inc.
Home-page: https://github.com/XanaduAI/pennylane
Author: 
Author-email: 
License: Apache License 2.0
Location: /Users/matthews/.pyenv/versions/3.9.13/envs/pennylane/lib/python3.9/site-packages
Requires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, retworkx, scipy, semantic-version, toml
Required-by: PennyLane-Lightning

Platform info:           macOS-12.6.1-arm64-arm-64bit
Python version:          3.9.13
Numpy version:           1.23.2
Scipy version:           1.9.0
Installed devices:
- default.gaussian (PennyLane-0.27.0)
- default.mixed (PennyLane-0.27.0)
- default.qubit (PennyLane-0.27.0)
- default.qubit.autograd (PennyLane-0.27.0)
- default.qubit.jax (PennyLane-0.27.0)
- default.qubit.tf (PennyLane-0.27.0)
- default.qubit.torch (PennyLane-0.27.0)
- default.qutrit (PennyLane-0.27.0)
- null.qubit (PennyLane-0.27.0)
- lightning.qubit (PennyLane-Lightning-0.26.1)
```


### Existing GitHub issues

- [X] I have searched existing GitHub issues to make sure the issue does not already exist.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pennylane/ops/functions/matrix.py`
Content:
```
1 # Copyright 2018-2021 Xanadu Quantum Technologies Inc.
2 
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 
7 #     http://www.apache.org/licenses/LICENSE-2.0
8 
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 """
15 This module contains the qml.matrix function.
16 """
17 # pylint: disable=protected-access
18 import pennylane as qml
19 
20 
21 @qml.op_transform
22 def matrix(op, *, wire_order=None):
23     r"""The matrix representation of an operation or quantum circuit.
24 
25     Args:
26         op (.Operator, pennylane.QNode, .QuantumTape, or Callable): An operator, quantum node, tape,
27             or function that applies quantum operations.
28         wire_order (Sequence[Any], optional): Order of the wires in the quantum circuit.
29             Defaults to the order in which the wires appear in the quantum function.
30 
31     Returns:
32         tensor_like or function: Function which accepts the same arguments as the QNode or quantum
33         function. When called, this function will return the unitary matrix in the appropriate
34         autodiff framework (Autograd, TensorFlow, PyTorch, JAX) given its parameters.
35 
36     **Example**
37 
38     Given an instantiated operator, ``qml.matrix`` returns the matrix representation:
39 
40     >>> op = qml.RX(0.54, wires=0)
41     >>> qml.matrix(op)
42     [[0.9637709+0.j         0.       -0.26673144j]
43     [0.       -0.26673144j 0.9637709+0.j        ]]
44 
45     It can also be used in a functional form:
46 
47     >>> x = torch.tensor(0.6, requires_grad=True)
48     >>> matrix_fn = qml.matrix(qml.RX)
49     >>> matrix_fn(x, wires=0)
50     tensor([[0.9553+0.0000j, 0.0000-0.2955j],
51             [0.0000-0.2955j, 0.9553+0.0000j]], grad_fn=<AddBackward0>)
52 
53     In its functional form, it is fully differentiable with respect to gate arguments:
54 
55     >>> loss = torch.real(torch.trace(matrix_fn(x, wires=0)))
56     >>> loss.backward()
57     >>> x.grad
58     tensor(-0.5910)
59 
60     This operator transform can also be applied to QNodes, tapes, and quantum functions
61     that contain multiple operations; see Usage Details below for more details.
62 
63     .. details::
64         :title: Usage Details
65 
66         ``qml.matrix`` can also be used with QNodes, tapes, or quantum functions that
67         contain multiple operations.
68 
69         Consider the following quantum function:
70 
71         .. code-block:: python3
72 
73             def circuit(theta):
74                 qml.RX(theta, wires=1)
75                 qml.PauliZ(wires=0)
76 
77         We can use ``qml.matrix`` to generate a new function that returns the unitary matrix
78         corresponding to the function ``circuit``:
79 
80         >>> matrix_fn = qml.matrix(circuit)
81         >>> theta = np.pi / 4
82         >>> matrix_fn(theta)
83         array([[ 0.92387953+0.j,  0.+0.j ,  0.-0.38268343j,  0.+0.j],
84         [ 0.+0.j,  -0.92387953+0.j,  0.+0.j,  0. +0.38268343j],
85         [ 0. -0.38268343j,  0.+0.j,  0.92387953+0.j,  0.+0.j],
86         [ 0.+0.j,  0.+0.38268343j,  0.+0.j,  -0.92387953+0.j]])
87 
88         Note that since ``wire_order`` was not specified, the default order ``[1, 0]`` for ``circuit``
89         was used, and the unitary matrix corresponds to the operation :math:`Z\otimes R_X(\theta)`. To
90         obtain the matrix for :math:`R_X(\theta)\otimes Z`, specify ``wire_order=[0, 1]`` in the
91         function call:
92 
93         >>> matrix = qml.matrix(circuit, wire_order=[0, 1])
94 
95         You can also get the unitary matrix for operations on a subspace of a larger Hilbert space. For
96         example, with the same function ``circuit`` and ``wire_order=["a", 0, "b", 1]`` you obtain the
97         :math:`16\times 16` matrix for the operation :math:`I\otimes Z\otimes I\otimes  R_X(\theta)`.
98 
99         This unitary matrix can also be used in differentiable calculations. For example, consider the
100         following cost function:
101 
102         .. code-block:: python
103 
104             def circuit(theta):
105                 qml.RX(theta, wires=1) qml.PauliZ(wires=0)
106                 qml.CNOT(wires=[0, 1])
107 
108             def cost(theta):
109                 matrix = qml.matrix(circuit)(theta)
110                 return np.real(np.trace(matrix))
111 
112         Since this cost function returns a real scalar as a function of ``theta``, we can differentiate
113         it:
114 
115         >>> theta = np.array(0.3, requires_grad=True)
116         >>> cost(theta)
117         1.9775421558720845
118         >>> qml.grad(cost)(theta)
119         -0.14943813247359922
120     """
121     if isinstance(op, qml.operation.Tensor) and wire_order is not None:
122         op = 1.0 * op  # convert to a Hamiltonian
123 
124     if isinstance(op, qml.Hamiltonian):
125         return qml.utils.sparse_hamiltonian(op, wires=wire_order).toarray()
126 
127     return op.matrix(wire_order=wire_order)
128 
129 
130 @matrix.tape_transform
131 def _matrix(tape, wire_order=None):
132     """Defines how matrix works if applied to a tape containing multiple operations."""
133     params = tape.get_parameters(trainable_only=False)
134     interface = qml.math.get_interface(*params)
135 
136     wire_order = wire_order or tape.wires
137 
138     # initialize the unitary matrix
139     result = qml.math.eye(2 ** len(wire_order), like=interface)
140 
141     for op in tape.operations:
142         U = matrix(op, wire_order=wire_order)
143         # Coerce the matrices U and result and use matrix multiplication. Broadcasted axes
144         # are handled correctly automatically by ``matmul`` (See e.g. NumPy documentation)
145         result = qml.math.matmul(*qml.math.coerce([U, result], like=interface), like=interface)
146 
147     return result
148
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pennylane/ops/functions/matrix.py b/pennylane/ops/functions/matrix.py
--- a/pennylane/ops/functions/matrix.py
+++ b/pennylane/ops/functions/matrix.py
@@ -130,6 +130,8 @@
 @matrix.tape_transform
 def _matrix(tape, wire_order=None):
     """Defines how matrix works if applied to a tape containing multiple operations."""
+    if not tape.wires:
+        raise qml.operation.MatrixUndefinedError
     params = tape.get_parameters(trainable_only=False)
     interface = qml.math.get_interface(*params)

{"golden_diff": "diff --git a/pennylane/ops/functions/matrix.py b/pennylane/ops/functions/matrix.py\n--- a/pennylane/ops/functions/matrix.py\n+++ b/pennylane/ops/functions/matrix.py\n@@ -130,6 +130,8 @@\n @matrix.tape_transform\r\n def _matrix(tape, wire_order=None):\r\n     \"\"\"Defines how matrix works if applied to a tape containing multiple operations.\"\"\"\r\n+    if not tape.wires:\r\n+        raise qml.operation.MatrixUndefinedError\r\n     params = tape.get_parameters(trainable_only=False)\r\n     interface = qml.math.get_interface(*params)\n", "issue": "[BUG] qml.matrix(op) and op.matrix() are different for Barrier and WireCut\n### Expected behavior\n\nI expected them both to pass, or both to fail.\n\n### Actual behavior\n\n`qml.matrix(qml.Barrier(0))` passed, `qml.Barrier(0).matrix()` failed. Same for `qml.WireCut`.\n\n### Additional information\n\nAttached source code is for Barrier, but the same thing happens with WireCut.\n\n### Source code\n\n```shell\n>>> import pennylane as qml\r\n>>> op = qml.Barrier(0)\r\n>>> qml.matrix(op)\r\narray([[1.]])\r\n>>> op.matrix()\r\nTraceback (most recent call last):\r\n  File \"<stdin>\", line 1, in <module>\r\n  File \"/Users/matthews/src/github.com/PennyLaneAI/pennylane/pennylane/operation.py\", line 1405, in matrix\r\n    canonical_matrix = self.compute_matrix(*self.parameters, **self.hyperparameters)\r\n  File \"/Users/matthews/src/github.com/PennyLaneAI/pennylane/pennylane/operation.py\", line 446, in compute_matrix\r\n    raise MatrixUndefinedError\r\npennylane.operation.MatrixUndefinedError\n```\n\n\n### Tracebacks\n\n_No response_\n\n### System information\n\n```shell\nName: PennyLane\r\nVersion: 0.27.0\r\nSummary: PennyLane is a Python quantum machine learning library by Xanadu Inc.\r\nHome-page: https://github.com/XanaduAI/pennylane\r\nAuthor: \r\nAuthor-email: \r\nLicense: Apache License 2.0\r\nLocation: /Users/matthews/.pyenv/versions/3.9.13/envs/pennylane/lib/python3.9/site-packages\r\nRequires: appdirs, autograd, autoray, cachetools, networkx, numpy, pennylane-lightning, requests, retworkx, scipy, semantic-version, toml\r\nRequired-by: PennyLane-Lightning\r\n\r\nPlatform info:           macOS-12.6.1-arm64-arm-64bit\r\nPython version:          3.9.13\r\nNumpy version:           1.23.2\r\nScipy version:           1.9.0\r\nInstalled devices:\r\n- default.gaussian (PennyLane-0.27.0)\r\n- default.mixed (PennyLane-0.27.0)\r\n- default.qubit (PennyLane-0.27.0)\r\n- default.qubit.autograd (PennyLane-0.27.0)\r\n- default.qubit.jax (PennyLane-0.27.0)\r\n- default.qubit.tf (PennyLane-0.27.0)\r\n- default.qubit.torch (PennyLane-0.27.0)\r\n- default.qutrit (PennyLane-0.27.0)\r\n- null.qubit (PennyLane-0.27.0)\r\n- lightning.qubit (PennyLane-Lightning-0.26.1)\n```\n\n\n### Existing GitHub issues\n\n- [X] I have searched existing GitHub issues to make sure the issue does not already exist.\n", "before_files": [{"content": "# Copyright 2018-2021 Xanadu Quantum Technologies Inc.\r\n\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n\r\n#     http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nThis module contains the qml.matrix function.\r\n\"\"\"\r\n# pylint: disable=protected-access\r\nimport pennylane as qml\r\n\r\n\r\n@qml.op_transform\r\ndef matrix(op, *, wire_order=None):\r\n    r\"\"\"The matrix representation of an operation or quantum circuit.\r\n\r\n    Args:\r\n        op (.Operator, pennylane.QNode, .QuantumTape, or Callable): An operator, quantum node, tape,\r\n            or function that applies quantum operations.\r\n        wire_order (Sequence[Any], optional): Order of the wires in the quantum circuit.\r\n            Defaults to the order in which the wires appear in the quantum function.\r\n\r\n    Returns:\r\n        tensor_like or function: Function which accepts the same arguments as the QNode or quantum\r\n        function. When called, this function will return the unitary matrix in the appropriate\r\n        autodiff framework (Autograd, TensorFlow, PyTorch, JAX) given its parameters.\r\n\r\n    **Example**\r\n\r\n    Given an instantiated operator, ``qml.matrix`` returns the matrix representation:\r\n\r\n    >>> op = qml.RX(0.54, wires=0)\r\n    >>> qml.matrix(op)\r\n    [[0.9637709+0.j         0.       -0.26673144j]\r\n    [0.       -0.26673144j 0.9637709+0.j        ]]\r\n\r\n    It can also be used in a functional form:\r\n\r\n    >>> x = torch.tensor(0.6, requires_grad=True)\r\n    >>> matrix_fn = qml.matrix(qml.RX)\r\n    >>> matrix_fn(x, wires=0)\r\n    tensor([[0.9553+0.0000j, 0.0000-0.2955j],\r\n            [0.0000-0.2955j, 0.9553+0.0000j]], grad_fn=<AddBackward0>)\r\n\r\n    In its functional form, it is fully differentiable with respect to gate arguments:\r\n\r\n    >>> loss = torch.real(torch.trace(matrix_fn(x, wires=0)))\r\n    >>> loss.backward()\r\n    >>> x.grad\r\n    tensor(-0.5910)\r\n\r\n    This operator transform can also be applied to QNodes, tapes, and quantum functions\r\n    that contain multiple operations; see Usage Details below for more details.\r\n\r\n    .. details::\r\n        :title: Usage Details\r\n\r\n        ``qml.matrix`` can also be used with QNodes, tapes, or quantum functions that\r\n        contain multiple operations.\r\n\r\n        Consider the following quantum function:\r\n\r\n        .. code-block:: python3\r\n\r\n            def circuit(theta):\r\n                qml.RX(theta, wires=1)\r\n                qml.PauliZ(wires=0)\r\n\r\n        We can use ``qml.matrix`` to generate a new function that returns the unitary matrix\r\n        corresponding to the function ``circuit``:\r\n\r\n        >>> matrix_fn = qml.matrix(circuit)\r\n        >>> theta = np.pi / 4\r\n        >>> matrix_fn(theta)\r\n        array([[ 0.92387953+0.j,  0.+0.j ,  0.-0.38268343j,  0.+0.j],\r\n        [ 0.+0.j,  -0.92387953+0.j,  0.+0.j,  0. +0.38268343j],\r\n        [ 0. -0.38268343j,  0.+0.j,  0.92387953+0.j,  0.+0.j],\r\n        [ 0.+0.j,  0.+0.38268343j,  0.+0.j,  -0.92387953+0.j]])\r\n\r\n        Note that since ``wire_order`` was not specified, the default order ``[1, 0]`` for ``circuit``\r\n        was used, and the unitary matrix corresponds to the operation :math:`Z\\otimes R_X(\\theta)`. To\r\n        obtain the matrix for :math:`R_X(\\theta)\\otimes Z`, specify ``wire_order=[0, 1]`` in the\r\n        function call:\r\n\r\n        >>> matrix = qml.matrix(circuit, wire_order=[0, 1])\r\n\r\n        You can also get the unitary matrix for operations on a subspace of a larger Hilbert space. For\r\n        example, with the same function ``circuit`` and ``wire_order=[\"a\", 0, \"b\", 1]`` you obtain the\r\n        :math:`16\\times 16` matrix for the operation :math:`I\\otimes Z\\otimes I\\otimes  R_X(\\theta)`.\r\n\r\n        This unitary matrix can also be used in differentiable calculations. For example, consider the\r\n        following cost function:\r\n\r\n        .. code-block:: python\r\n\r\n            def circuit(theta):\r\n                qml.RX(theta, wires=1) qml.PauliZ(wires=0)\r\n                qml.CNOT(wires=[0, 1])\r\n\r\n            def cost(theta):\r\n                matrix = qml.matrix(circuit)(theta)\r\n                return np.real(np.trace(matrix))\r\n\r\n        Since this cost function returns a real scalar as a function of ``theta``, we can differentiate\r\n        it:\r\n\r\n        >>> theta = np.array(0.3, requires_grad=True)\r\n        >>> cost(theta)\r\n        1.9775421558720845\r\n        >>> qml.grad(cost)(theta)\r\n        -0.14943813247359922\r\n    \"\"\"\r\n    if isinstance(op, qml.operation.Tensor) and wire_order is not None:\r\n        op = 1.0 * op  # convert to a Hamiltonian\r\n\r\n    if isinstance(op, qml.Hamiltonian):\r\n        return qml.utils.sparse_hamiltonian(op, wires=wire_order).toarray()\r\n\r\n    return op.matrix(wire_order=wire_order)\r\n\r\n\r\n@matrix.tape_transform\r\ndef _matrix(tape, wire_order=None):\r\n    \"\"\"Defines how matrix works if applied to a tape containing multiple operations.\"\"\"\r\n    params = tape.get_parameters(trainable_only=False)\r\n    interface = qml.math.get_interface(*params)\r\n\r\n    wire_order = wire_order or tape.wires\r\n\r\n    # initialize the unitary matrix\r\n    result = qml.math.eye(2 ** len(wire_order), like=interface)\r\n\r\n    for op in tape.operations:\r\n        U = matrix(op, wire_order=wire_order)\r\n        # Coerce the matrices U and result and use matrix multiplication. Broadcasted axes\r\n        # are handled correctly automatically by ``matmul`` (See e.g. NumPy documentation)\r\n        result = qml.math.matmul(*qml.math.coerce([U, result], like=interface), like=interface)\r\n\r\n    return result\r\n", "path": "pennylane/ops/functions/matrix.py"}], "after_files": [{"content": "# Copyright 2018-2021 Xanadu Quantum Technologies Inc.\r\n\r\n# Licensed under the Apache License, Version 2.0 (the \"License\");\r\n# you may not use this file except in compliance with the License.\r\n# You may obtain a copy of the License at\r\n\r\n#     http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n# Unless required by applicable law or agreed to in writing, software\r\n# distributed under the License is distributed on an \"AS IS\" BASIS,\r\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n# See the License for the specific language governing permissions and\r\n# limitations under the License.\r\n\"\"\"\r\nThis module contains the qml.matrix function.\r\n\"\"\"\r\n# pylint: disable=protected-access\r\nimport pennylane as qml\r\n\r\n\r\n@qml.op_transform\r\ndef matrix(op, *, wire_order=None):\r\n    r\"\"\"The matrix representation of an operation or quantum circuit.\r\n\r\n    Args:\r\n        op (.Operator, pennylane.QNode, .QuantumTape, or Callable): An operator, quantum node, tape,\r\n            or function that applies quantum operations.\r\n        wire_order (Sequence[Any], optional): Order of the wires in the quantum circuit.\r\n            Defaults to the order in which the wires appear in the quantum function.\r\n\r\n    Returns:\r\n        tensor_like or function: Function which accepts the same arguments as the QNode or quantum\r\n        function. When called, this function will return the unitary matrix in the appropriate\r\n        autodiff framework (Autograd, TensorFlow, PyTorch, JAX) given its parameters.\r\n\r\n    **Example**\r\n\r\n    Given an instantiated operator, ``qml.matrix`` returns the matrix representation:\r\n\r\n    >>> op = qml.RX(0.54, wires=0)\r\n    >>> qml.matrix(op)\r\n    [[0.9637709+0.j         0.       -0.26673144j]\r\n    [0.       -0.26673144j 0.9637709+0.j        ]]\r\n\r\n    It can also be used in a functional form:\r\n\r\n    >>> x = torch.tensor(0.6, requires_grad=True)\r\n    >>> matrix_fn = qml.matrix(qml.RX)\r\n    >>> matrix_fn(x, wires=0)\r\n    tensor([[0.9553+0.0000j, 0.0000-0.2955j],\r\n            [0.0000-0.2955j, 0.9553+0.0000j]], grad_fn=<AddBackward0>)\r\n\r\n    In its functional form, it is fully differentiable with respect to gate arguments:\r\n\r\n    >>> loss = torch.real(torch.trace(matrix_fn(x, wires=0)))\r\n    >>> loss.backward()\r\n    >>> x.grad\r\n    tensor(-0.5910)\r\n\r\n    This operator transform can also be applied to QNodes, tapes, and quantum functions\r\n    that contain multiple operations; see Usage Details below for more details.\r\n\r\n    .. details::\r\n        :title: Usage Details\r\n\r\n        ``qml.matrix`` can also be used with QNodes, tapes, or quantum functions that\r\n        contain multiple operations.\r\n\r\n        Consider the following quantum function:\r\n\r\n        .. code-block:: python3\r\n\r\n            def circuit(theta):\r\n                qml.RX(theta, wires=1)\r\n                qml.PauliZ(wires=0)\r\n\r\n        We can use ``qml.matrix`` to generate a new function that returns the unitary matrix\r\n        corresponding to the function ``circuit``:\r\n\r\n        >>> matrix_fn = qml.matrix(circuit)\r\n        >>> theta = np.pi / 4\r\n        >>> matrix_fn(theta)\r\n        array([[ 0.92387953+0.j,  0.+0.j ,  0.-0.38268343j,  0.+0.j],\r\n        [ 0.+0.j,  -0.92387953+0.j,  0.+0.j,  0. +0.38268343j],\r\n        [ 0. -0.38268343j,  0.+0.j,  0.92387953+0.j,  0.+0.j],\r\n        [ 0.+0.j,  0.+0.38268343j,  0.+0.j,  -0.92387953+0.j]])\r\n\r\n        Note that since ``wire_order`` was not specified, the default order ``[1, 0]`` for ``circuit``\r\n        was used, and the unitary matrix corresponds to the operation :math:`Z\\otimes R_X(\\theta)`. To\r\n        obtain the matrix for :math:`R_X(\\theta)\\otimes Z`, specify ``wire_order=[0, 1]`` in the\r\n        function call:\r\n\r\n        >>> matrix = qml.matrix(circuit, wire_order=[0, 1])\r\n\r\n        You can also get the unitary matrix for operations on a subspace of a larger Hilbert space. For\r\n        example, with the same function ``circuit`` and ``wire_order=[\"a\", 0, \"b\", 1]`` you obtain the\r\n        :math:`16\\times 16` matrix for the operation :math:`I\\otimes Z\\otimes I\\otimes  R_X(\\theta)`.\r\n\r\n        This unitary matrix can also be used in differentiable calculations. For example, consider the\r\n        following cost function:\r\n\r\n        .. code-block:: python\r\n\r\n            def circuit(theta):\r\n                qml.RX(theta, wires=1) qml.PauliZ(wires=0)\r\n                qml.CNOT(wires=[0, 1])\r\n\r\n            def cost(theta):\r\n                matrix = qml.matrix(circuit)(theta)\r\n                return np.real(np.trace(matrix))\r\n\r\n        Since this cost function returns a real scalar as a function of ``theta``, we can differentiate\r\n        it:\r\n\r\n        >>> theta = np.array(0.3, requires_grad=True)\r\n        >>> cost(theta)\r\n        1.9775421558720845\r\n        >>> qml.grad(cost)(theta)\r\n        -0.14943813247359922\r\n    \"\"\"\r\n    if isinstance(op, qml.operation.Tensor) and wire_order is not None:\r\n        op = 1.0 * op  # convert to a Hamiltonian\r\n\r\n    if isinstance(op, qml.Hamiltonian):\r\n        return qml.utils.sparse_hamiltonian(op, wires=wire_order).toarray()\r\n\r\n    return op.matrix(wire_order=wire_order)\r\n\r\n\r\n@matrix.tape_transform\r\ndef _matrix(tape, wire_order=None):\r\n    \"\"\"Defines how matrix works if applied to a tape containing multiple operations.\"\"\"\r\n    if not tape.wires:\r\n        raise qml.operation.MatrixUndefinedError\r\n    params = tape.get_parameters(trainable_only=False)\r\n    interface = qml.math.get_interface(*params)\r\n\r\n    wire_order = wire_order or tape.wires\r\n\r\n    # initialize the unitary matrix\r\n    result = qml.math.eye(2 ** len(wire_order), like=interface)\r\n\r\n    for op in tape.operations:\r\n        U = matrix(op, wire_order=wire_order)\r\n        # Coerce the matrices U and result and use matrix multiplication. Broadcasted axes\r\n        # are handled correctly automatically by ``matmul`` (See e.g. NumPy documentation)\r\n        result = qml.math.matmul(*qml.math.coerce([U, result], like=interface), like=interface)\r\n\r\n    return result\r\n", "path": "pennylane/ops/functions/matrix.py"}]}