We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] Derivatives of `qml.CommutingEvolution`
In cleaning warnings from the test suite, I found this warning:

```
templates/test_subroutines/test_commuting_evolution.py::TestGradients::test_differentiable_hamiltonian
  /Users/christina/Prog/pl/lib/python3.8/site-packages/autograd/tracer.py:14: UserWarning: Output seems independent of input.
    warnings.warn("Output seems independent of input.")
```

The effect of `CommutingEvolution` on the state did not change with the time.  
This problems seems to stem from [commuting_evolution.py Line 160](https://github.com/PennyLaneAI/pennylane/blob/e55f463bcbca1832505d9440d2f5144543f944fe/pennylane/templates/subroutines/commuting_evolution.py#L160):
```
        return qml.templates.ApproxTimeEvolution(hamiltonian, time_and_coeffs[1], 1).decomposition()
```
This line incorrectly indexes into `time_and_coeffs` to try and extract the time.  It should instead use `time_and_coeffs[0]`.

Upon fixing that bug, we now find that parameter shift no longer works for `CommutingEvolution`.  

These two tests start to fail:
```
==================================================================================== short test summary info ====================================================================================
FAILED templates/test_subroutines/test_commuting_evolution.py::TestGradients::test_two_term_case - assert False
FAILED templates/test_subroutines/test_commuting_evolution.py::TestGradients::test_four_term_case - assert False
```

The tests that fail manually specify the frequencies. If the frequencies are specified, the operation sets its own `grad_recipe`.  This `grad_recipe` gives incorrect results.  I have yet to track down the problem with the `grad_recipe` property.


In summary, fixing the bug in the creation of the `ApproxTimeEvolution` operation allows finite difference derivatives and derivatives for operations without specified frequencies to work correctly.  Since the finite-difference derivatives are now correct, we can see that the parameter-shift gradients never worked correctly.



--- 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/templates/subroutines/commuting_evolution.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 r"""
15 Contains the CommutingEvolution template.
16 """
17 # pylint: disable-msg=too-many-arguments,import-outside-toplevel
18 import pennylane as qml
19 from pennylane.operation import Operation, AnyWires
20 
21 
22 class CommutingEvolution(Operation):
23     r"""Applies the time-evolution operator for a Hamiltonian expressed as a linear combination
24     of mutually commuting Pauli words.
25 
26     A commuting Hamiltonian is of the form
27 
28     .. math:: H \ = \ \displaystyle\sum_{j} c_j P_j,
29 
30     where :math:`P_j` are mutually commutative Pauli words and :math:`c_j` are real coefficients.
31     The time-evolution under a commuting Hamiltonian is given by a unitary of the form
32 
33     .. math::
34 
35         U(t) \ = \ e^{-i H t} \ = \exp(-i t \displaystyle\sum_j c_j P_j) =
36         \displaystyle\prod_j \exp(-i t c_j P_j).
37 
38     If the Hamiltonian has a small number of unique eigenvalues, partial derivatives of observable
39     expectation values, i.e.
40 
41     .. math:: \langle 0 | W(t)^\dagger O W(t) | 0 \rangle,
42 
43     where :math:`W(t) = V U(t) Y` for some :math:`V` and :math:`Y`, taken with respect to
44     :math:`t` may be efficiently computed through generalized parameter shift rules. When
45     initialized, this template will automatically compute the parameter-shift rule if given the
46     Hamiltonian's eigenvalue frequencies, i.e., the unique positive differences between
47     eigenvalues.
48 
49     .. warning::
50 
51        This template uses the :class:`~.ApproxTimeEvolution` operation with ``n=1`` in order to
52        implement the time evolution, as a single-step Trotterization is exact for a commuting
53        Hamiltonian.
54 
55        - If the input Hamiltonian contains Pauli words which do not commute, the
56          compilation of the time evolution operator to a sequence of gates will
57          not equate to the exact propagation under the given Hamiltonian.
58 
59        - Furthermore, if the specified frequencies do not correspond to the
60          true eigenvalue frequency spectrum of the commuting Hamiltonian,
61          computed gradients will be incorrect in general.
62 
63     Args:
64         hamiltonian (.Hamiltonian): The commuting Hamiltonian defining the time-evolution operator.
65            The Hamiltonian must be explicitly written
66            in terms of products of Pauli gates (:class:`~.PauliX`, :class:`~.PauliY`,
67            :class:`~.PauliZ`, and :class:`~.Identity`).
68         time (int or float): The time of evolution, namely the parameter :math:`t` in :math:`e^{- i H t}`.
69 
70     Keyword args:
71         frequencies (tuple[int or float]): The unique positive differences between eigenvalues in
72             the spectrum of the Hamiltonian. If the frequencies are not given, the cost function
73             partial derivative will be computed using the standard two-term shift rule applied to
74             the constituent Pauli words in the Hamiltonian individually.
75 
76         shifts (tuple[int or float]): The parameter shifts to use in obtaining the
77             generalized parameter shift rules. If unspecified, equidistant shifts are used.
78 
79     .. details::
80         :title: Usage Details
81 
82         The template is used inside a qnode:
83 
84         .. code-block:: python
85 
86             import pennylane as qml
87 
88             n_wires = 2
89             dev = qml.device('default.qubit', wires=n_wires)
90 
91             coeffs = [1, -1]
92             obs = [qml.PauliX(0) @ qml.PauliY(1), qml.PauliY(0) @ qml.PauliX(1)]
93             hamiltonian = qml.Hamiltonian(coeffs, obs)
94             frequencies = (2, 4)
95 
96             @qml.qnode(dev)
97             def circuit(time):
98                 qml.PauliX(0)
99                 qml.CommutingEvolution(hamiltonian, time, frequencies)
100                 return qml.expval(qml.PauliZ(0))
101 
102         >>> circuit(1)
103         0.6536436208636115
104     """
105 
106     num_wires = AnyWires
107     grad_method = None
108 
109     def __init__(self, hamiltonian, time, frequencies=None, shifts=None, do_queue=True, id=None):
110         # pylint: disable=import-outside-toplevel
111         from pennylane.gradients.general_shift_rules import (
112             generate_shift_rule,
113         )
114 
115         if not isinstance(hamiltonian, qml.Hamiltonian):
116             type_name = type(hamiltonian).__name__
117             raise TypeError(f"hamiltonian must be of type pennylane.Hamiltonian, got {type_name}")
118 
119         trainable_hamiltonian = qml.math.requires_grad(hamiltonian.coeffs)
120         if frequencies is not None and not trainable_hamiltonian:
121             c, s = generate_shift_rule(frequencies, shifts).T
122             recipe = qml.math.stack([c, qml.math.ones_like(c), s]).T
123             self.grad_recipe = (recipe,) + (None,) * len(hamiltonian.data)
124             self.grad_method = "A"
125 
126         self._hyperparameters = {
127             "hamiltonian": hamiltonian,
128             "frequencies": frequencies,
129             "shifts": shifts,
130         }
131 
132         super().__init__(
133             time, *hamiltonian.parameters, wires=hamiltonian.wires, do_queue=do_queue, id=id
134         )
135 
136     @staticmethod
137     def compute_decomposition(
138         *time_and_coeffs, wires, hamiltonian, **kwargs
139     ):  # pylint: disable=arguments-differ,unused-argument
140         r"""Representation of the operator as a product of other operators.
141 
142         .. math:: O = O_1 O_2 \dots O_n.
143 
144         Args:
145             time_and_coeffs (list[tensor_like or float]): list of coefficients of the Hamiltonian, prepended by the time
146                 variable
147             wires (Any or Iterable[Any]): wires that the operator acts on
148             hamiltonian (.Hamiltonian): The commuting Hamiltonian defining the time-evolution operator.
149             frequencies (tuple[int or float]): The unique positive differences between eigenvalues in
150                 the spectrum of the Hamiltonian.
151             shifts (tuple[int or float]): The parameter shifts to use in obtaining the
152                 generalized parameter shift rules. If unspecified, equidistant shifts are used.
153 
154         .. seealso:: :meth:`~.CommutingEvolution.decomposition`.
155 
156         Returns:
157             list[.Operator]: decomposition of the operator
158         """
159         # uses standard PauliRot decomposition through ApproxTimeEvolution.
160         hamiltonian = qml.Hamiltonian(time_and_coeffs[1:], hamiltonian.ops)
161         return qml.templates.ApproxTimeEvolution(hamiltonian, time_and_coeffs[1], 1).decomposition()
162 
163     def adjoint(self):  # pylint: disable=arguments-differ
164 
165         hamiltonian = qml.Hamiltonian(self.parameters[1:], self.hyperparameters["hamiltonian"].ops)
166         time = self.parameters[0]
167         frequencies = self.hyperparameters["frequencies"]
168         shifts = self.hyperparameters["shifts"]
169 
170         return CommutingEvolution(hamiltonian, -time, frequencies, shifts)
171
```
--- 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/templates/subroutines/commuting_evolution.py b/pennylane/templates/subroutines/commuting_evolution.py
--- a/pennylane/templates/subroutines/commuting_evolution.py
+++ b/pennylane/templates/subroutines/commuting_evolution.py
@@ -135,7 +135,7 @@
 
     @staticmethod
     def compute_decomposition(
-        *time_and_coeffs, wires, hamiltonian, **kwargs
+        time, *coeffs, wires, hamiltonian, **kwargs
     ):  # pylint: disable=arguments-differ,unused-argument
         r"""Representation of the operator as a product of other operators.
 
@@ -157,8 +157,8 @@
             list[.Operator]: decomposition of the operator
         """
         # uses standard PauliRot decomposition through ApproxTimeEvolution.
-        hamiltonian = qml.Hamiltonian(time_and_coeffs[1:], hamiltonian.ops)
-        return qml.templates.ApproxTimeEvolution(hamiltonian, time_and_coeffs[1], 1).decomposition()
+        hamiltonian = qml.Hamiltonian(coeffs, hamiltonian.ops)
+        return qml.ApproxTimeEvolution(hamiltonian, time, 1)
 
     def adjoint(self):  # pylint: disable=arguments-differ

{"golden_diff": "diff --git a/pennylane/templates/subroutines/commuting_evolution.py b/pennylane/templates/subroutines/commuting_evolution.py\n--- a/pennylane/templates/subroutines/commuting_evolution.py\n+++ b/pennylane/templates/subroutines/commuting_evolution.py\n@@ -135,7 +135,7 @@\n \r\n     @staticmethod\r\n     def compute_decomposition(\r\n-        *time_and_coeffs, wires, hamiltonian, **kwargs\r\n+        time, *coeffs, wires, hamiltonian, **kwargs\r\n     ):  # pylint: disable=arguments-differ,unused-argument\r\n         r\"\"\"Representation of the operator as a product of other operators.\r\n \r\n@@ -157,8 +157,8 @@\n             list[.Operator]: decomposition of the operator\r\n         \"\"\"\r\n         # uses standard PauliRot decomposition through ApproxTimeEvolution.\r\n-        hamiltonian = qml.Hamiltonian(time_and_coeffs[1:], hamiltonian.ops)\r\n-        return qml.templates.ApproxTimeEvolution(hamiltonian, time_and_coeffs[1], 1).decomposition()\r\n+        hamiltonian = qml.Hamiltonian(coeffs, hamiltonian.ops)\r\n+        return qml.ApproxTimeEvolution(hamiltonian, time, 1)\r\n \r\n     def adjoint(self):  # pylint: disable=arguments-differ\n", "issue": "[BUG] Derivatives of `qml.CommutingEvolution`\nIn cleaning warnings from the test suite, I found this warning:\r\n\r\n```\r\ntemplates/test_subroutines/test_commuting_evolution.py::TestGradients::test_differentiable_hamiltonian\r\n  /Users/christina/Prog/pl/lib/python3.8/site-packages/autograd/tracer.py:14: UserWarning: Output seems independent of input.\r\n    warnings.warn(\"Output seems independent of input.\")\r\n```\r\n\r\nThe effect of `CommutingEvolution` on the state did not change with the time.  \r\nThis problems seems to stem from [commuting_evolution.py Line 160](https://github.com/PennyLaneAI/pennylane/blob/e55f463bcbca1832505d9440d2f5144543f944fe/pennylane/templates/subroutines/commuting_evolution.py#L160):\r\n```\r\n        return qml.templates.ApproxTimeEvolution(hamiltonian, time_and_coeffs[1], 1).decomposition()\r\n```\r\nThis line incorrectly indexes into `time_and_coeffs` to try and extract the time.  It should instead use `time_and_coeffs[0]`.\r\n\r\nUpon fixing that bug, we now find that parameter shift no longer works for `CommutingEvolution`.  \r\n\r\nThese two tests start to fail:\r\n```\r\n==================================================================================== short test summary info ====================================================================================\r\nFAILED templates/test_subroutines/test_commuting_evolution.py::TestGradients::test_two_term_case - assert False\r\nFAILED templates/test_subroutines/test_commuting_evolution.py::TestGradients::test_four_term_case - assert False\r\n```\r\n\r\nThe tests that fail manually specify the frequencies. If the frequencies are specified, the operation sets its own `grad_recipe`.  This `grad_recipe` gives incorrect results.  I have yet to track down the problem with the `grad_recipe` property.\r\n\r\n\r\nIn summary, fixing the bug in the creation of the `ApproxTimeEvolution` operation allows finite difference derivatives and derivatives for operations without specified frequencies to work correctly.  Since the finite-difference derivatives are now correct, we can see that the parameter-shift gradients never worked correctly.\r\n\r\n\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\nr\"\"\"\r\nContains the CommutingEvolution template.\r\n\"\"\"\r\n# pylint: disable-msg=too-many-arguments,import-outside-toplevel\r\nimport pennylane as qml\r\nfrom pennylane.operation import Operation, AnyWires\r\n\r\n\r\nclass CommutingEvolution(Operation):\r\n    r\"\"\"Applies the time-evolution operator for a Hamiltonian expressed as a linear combination\r\n    of mutually commuting Pauli words.\r\n\r\n    A commuting Hamiltonian is of the form\r\n\r\n    .. math:: H \\ = \\ \\displaystyle\\sum_{j} c_j P_j,\r\n\r\n    where :math:`P_j` are mutually commutative Pauli words and :math:`c_j` are real coefficients.\r\n    The time-evolution under a commuting Hamiltonian is given by a unitary of the form\r\n\r\n    .. math::\r\n\r\n        U(t) \\ = \\ e^{-i H t} \\ = \\exp(-i t \\displaystyle\\sum_j c_j P_j) =\r\n        \\displaystyle\\prod_j \\exp(-i t c_j P_j).\r\n\r\n    If the Hamiltonian has a small number of unique eigenvalues, partial derivatives of observable\r\n    expectation values, i.e.\r\n\r\n    .. math:: \\langle 0 | W(t)^\\dagger O W(t) | 0 \\rangle,\r\n\r\n    where :math:`W(t) = V U(t) Y` for some :math:`V` and :math:`Y`, taken with respect to\r\n    :math:`t` may be efficiently computed through generalized parameter shift rules. When\r\n    initialized, this template will automatically compute the parameter-shift rule if given the\r\n    Hamiltonian's eigenvalue frequencies, i.e., the unique positive differences between\r\n    eigenvalues.\r\n\r\n    .. warning::\r\n\r\n       This template uses the :class:`~.ApproxTimeEvolution` operation with ``n=1`` in order to\r\n       implement the time evolution, as a single-step Trotterization is exact for a commuting\r\n       Hamiltonian.\r\n\r\n       - If the input Hamiltonian contains Pauli words which do not commute, the\r\n         compilation of the time evolution operator to a sequence of gates will\r\n         not equate to the exact propagation under the given Hamiltonian.\r\n\r\n       - Furthermore, if the specified frequencies do not correspond to the\r\n         true eigenvalue frequency spectrum of the commuting Hamiltonian,\r\n         computed gradients will be incorrect in general.\r\n\r\n    Args:\r\n        hamiltonian (.Hamiltonian): The commuting Hamiltonian defining the time-evolution operator.\r\n           The Hamiltonian must be explicitly written\r\n           in terms of products of Pauli gates (:class:`~.PauliX`, :class:`~.PauliY`,\r\n           :class:`~.PauliZ`, and :class:`~.Identity`).\r\n        time (int or float): The time of evolution, namely the parameter :math:`t` in :math:`e^{- i H t}`.\r\n\r\n    Keyword args:\r\n        frequencies (tuple[int or float]): The unique positive differences between eigenvalues in\r\n            the spectrum of the Hamiltonian. If the frequencies are not given, the cost function\r\n            partial derivative will be computed using the standard two-term shift rule applied to\r\n            the constituent Pauli words in the Hamiltonian individually.\r\n\r\n        shifts (tuple[int or float]): The parameter shifts to use in obtaining the\r\n            generalized parameter shift rules. If unspecified, equidistant shifts are used.\r\n\r\n    .. details::\r\n        :title: Usage Details\r\n\r\n        The template is used inside a qnode:\r\n\r\n        .. code-block:: python\r\n\r\n            import pennylane as qml\r\n\r\n            n_wires = 2\r\n            dev = qml.device('default.qubit', wires=n_wires)\r\n\r\n            coeffs = [1, -1]\r\n            obs = [qml.PauliX(0) @ qml.PauliY(1), qml.PauliY(0) @ qml.PauliX(1)]\r\n            hamiltonian = qml.Hamiltonian(coeffs, obs)\r\n            frequencies = (2, 4)\r\n\r\n            @qml.qnode(dev)\r\n            def circuit(time):\r\n                qml.PauliX(0)\r\n                qml.CommutingEvolution(hamiltonian, time, frequencies)\r\n                return qml.expval(qml.PauliZ(0))\r\n\r\n        >>> circuit(1)\r\n        0.6536436208636115\r\n    \"\"\"\r\n\r\n    num_wires = AnyWires\r\n    grad_method = None\r\n\r\n    def __init__(self, hamiltonian, time, frequencies=None, shifts=None, do_queue=True, id=None):\r\n        # pylint: disable=import-outside-toplevel\r\n        from pennylane.gradients.general_shift_rules import (\r\n            generate_shift_rule,\r\n        )\r\n\r\n        if not isinstance(hamiltonian, qml.Hamiltonian):\r\n            type_name = type(hamiltonian).__name__\r\n            raise TypeError(f\"hamiltonian must be of type pennylane.Hamiltonian, got {type_name}\")\r\n\r\n        trainable_hamiltonian = qml.math.requires_grad(hamiltonian.coeffs)\r\n        if frequencies is not None and not trainable_hamiltonian:\r\n            c, s = generate_shift_rule(frequencies, shifts).T\r\n            recipe = qml.math.stack([c, qml.math.ones_like(c), s]).T\r\n            self.grad_recipe = (recipe,) + (None,) * len(hamiltonian.data)\r\n            self.grad_method = \"A\"\r\n\r\n        self._hyperparameters = {\r\n            \"hamiltonian\": hamiltonian,\r\n            \"frequencies\": frequencies,\r\n            \"shifts\": shifts,\r\n        }\r\n\r\n        super().__init__(\r\n            time, *hamiltonian.parameters, wires=hamiltonian.wires, do_queue=do_queue, id=id\r\n        )\r\n\r\n    @staticmethod\r\n    def compute_decomposition(\r\n        *time_and_coeffs, wires, hamiltonian, **kwargs\r\n    ):  # pylint: disable=arguments-differ,unused-argument\r\n        r\"\"\"Representation of the operator as a product of other operators.\r\n\r\n        .. math:: O = O_1 O_2 \\dots O_n.\r\n\r\n        Args:\r\n            time_and_coeffs (list[tensor_like or float]): list of coefficients of the Hamiltonian, prepended by the time\r\n                variable\r\n            wires (Any or Iterable[Any]): wires that the operator acts on\r\n            hamiltonian (.Hamiltonian): The commuting Hamiltonian defining the time-evolution operator.\r\n            frequencies (tuple[int or float]): The unique positive differences between eigenvalues in\r\n                the spectrum of the Hamiltonian.\r\n            shifts (tuple[int or float]): The parameter shifts to use in obtaining the\r\n                generalized parameter shift rules. If unspecified, equidistant shifts are used.\r\n\r\n        .. seealso:: :meth:`~.CommutingEvolution.decomposition`.\r\n\r\n        Returns:\r\n            list[.Operator]: decomposition of the operator\r\n        \"\"\"\r\n        # uses standard PauliRot decomposition through ApproxTimeEvolution.\r\n        hamiltonian = qml.Hamiltonian(time_and_coeffs[1:], hamiltonian.ops)\r\n        return qml.templates.ApproxTimeEvolution(hamiltonian, time_and_coeffs[1], 1).decomposition()\r\n\r\n    def adjoint(self):  # pylint: disable=arguments-differ\r\n\r\n        hamiltonian = qml.Hamiltonian(self.parameters[1:], self.hyperparameters[\"hamiltonian\"].ops)\r\n        time = self.parameters[0]\r\n        frequencies = self.hyperparameters[\"frequencies\"]\r\n        shifts = self.hyperparameters[\"shifts\"]\r\n\r\n        return CommutingEvolution(hamiltonian, -time, frequencies, shifts)\r\n", "path": "pennylane/templates/subroutines/commuting_evolution.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\nr\"\"\"\r\nContains the CommutingEvolution template.\r\n\"\"\"\r\n# pylint: disable-msg=too-many-arguments,import-outside-toplevel\r\nimport pennylane as qml\r\nfrom pennylane.operation import Operation, AnyWires\r\n\r\n\r\nclass CommutingEvolution(Operation):\r\n    r\"\"\"Applies the time-evolution operator for a Hamiltonian expressed as a linear combination\r\n    of mutually commuting Pauli words.\r\n\r\n    A commuting Hamiltonian is of the form\r\n\r\n    .. math:: H \\ = \\ \\displaystyle\\sum_{j} c_j P_j,\r\n\r\n    where :math:`P_j` are mutually commutative Pauli words and :math:`c_j` are real coefficients.\r\n    The time-evolution under a commuting Hamiltonian is given by a unitary of the form\r\n\r\n    .. math::\r\n\r\n        U(t) \\ = \\ e^{-i H t} \\ = \\exp(-i t \\displaystyle\\sum_j c_j P_j) =\r\n        \\displaystyle\\prod_j \\exp(-i t c_j P_j).\r\n\r\n    If the Hamiltonian has a small number of unique eigenvalues, partial derivatives of observable\r\n    expectation values, i.e.\r\n\r\n    .. math:: \\langle 0 | W(t)^\\dagger O W(t) | 0 \\rangle,\r\n\r\n    where :math:`W(t) = V U(t) Y` for some :math:`V` and :math:`Y`, taken with respect to\r\n    :math:`t` may be efficiently computed through generalized parameter shift rules. When\r\n    initialized, this template will automatically compute the parameter-shift rule if given the\r\n    Hamiltonian's eigenvalue frequencies, i.e., the unique positive differences between\r\n    eigenvalues.\r\n\r\n    .. warning::\r\n\r\n       This template uses the :class:`~.ApproxTimeEvolution` operation with ``n=1`` in order to\r\n       implement the time evolution, as a single-step Trotterization is exact for a commuting\r\n       Hamiltonian.\r\n\r\n       - If the input Hamiltonian contains Pauli words which do not commute, the\r\n         compilation of the time evolution operator to a sequence of gates will\r\n         not equate to the exact propagation under the given Hamiltonian.\r\n\r\n       - Furthermore, if the specified frequencies do not correspond to the\r\n         true eigenvalue frequency spectrum of the commuting Hamiltonian,\r\n         computed gradients will be incorrect in general.\r\n\r\n    Args:\r\n        hamiltonian (.Hamiltonian): The commuting Hamiltonian defining the time-evolution operator.\r\n           The Hamiltonian must be explicitly written\r\n           in terms of products of Pauli gates (:class:`~.PauliX`, :class:`~.PauliY`,\r\n           :class:`~.PauliZ`, and :class:`~.Identity`).\r\n        time (int or float): The time of evolution, namely the parameter :math:`t` in :math:`e^{- i H t}`.\r\n\r\n    Keyword args:\r\n        frequencies (tuple[int or float]): The unique positive differences between eigenvalues in\r\n            the spectrum of the Hamiltonian. If the frequencies are not given, the cost function\r\n            partial derivative will be computed using the standard two-term shift rule applied to\r\n            the constituent Pauli words in the Hamiltonian individually.\r\n\r\n        shifts (tuple[int or float]): The parameter shifts to use in obtaining the\r\n            generalized parameter shift rules. If unspecified, equidistant shifts are used.\r\n\r\n    .. details::\r\n        :title: Usage Details\r\n\r\n        The template is used inside a qnode:\r\n\r\n        .. code-block:: python\r\n\r\n            import pennylane as qml\r\n\r\n            n_wires = 2\r\n            dev = qml.device('default.qubit', wires=n_wires)\r\n\r\n            coeffs = [1, -1]\r\n            obs = [qml.PauliX(0) @ qml.PauliY(1), qml.PauliY(0) @ qml.PauliX(1)]\r\n            hamiltonian = qml.Hamiltonian(coeffs, obs)\r\n            frequencies = (2, 4)\r\n\r\n            @qml.qnode(dev)\r\n            def circuit(time):\r\n                qml.PauliX(0)\r\n                qml.CommutingEvolution(hamiltonian, time, frequencies)\r\n                return qml.expval(qml.PauliZ(0))\r\n\r\n        >>> circuit(1)\r\n        0.6536436208636115\r\n    \"\"\"\r\n\r\n    num_wires = AnyWires\r\n    grad_method = None\r\n\r\n    def __init__(self, hamiltonian, time, frequencies=None, shifts=None, do_queue=True, id=None):\r\n        # pylint: disable=import-outside-toplevel\r\n        from pennylane.gradients.general_shift_rules import (\r\n            generate_shift_rule,\r\n        )\r\n\r\n        if not isinstance(hamiltonian, qml.Hamiltonian):\r\n            type_name = type(hamiltonian).__name__\r\n            raise TypeError(f\"hamiltonian must be of type pennylane.Hamiltonian, got {type_name}\")\r\n\r\n        trainable_hamiltonian = qml.math.requires_grad(hamiltonian.coeffs)\r\n        if frequencies is not None and not trainable_hamiltonian:\r\n            c, s = generate_shift_rule(frequencies, shifts).T\r\n            recipe = qml.math.stack([c, qml.math.ones_like(c), s]).T\r\n            self.grad_recipe = (recipe,) + (None,) * len(hamiltonian.data)\r\n            self.grad_method = \"A\"\r\n\r\n        self._hyperparameters = {\r\n            \"hamiltonian\": hamiltonian,\r\n            \"frequencies\": frequencies,\r\n            \"shifts\": shifts,\r\n        }\r\n\r\n        super().__init__(\r\n            time, *hamiltonian.parameters, wires=hamiltonian.wires, do_queue=do_queue, id=id\r\n        )\r\n\r\n    @staticmethod\r\n    def compute_decomposition(\r\n        time, *coeffs, wires, hamiltonian, **kwargs\r\n    ):  # pylint: disable=arguments-differ,unused-argument\r\n        r\"\"\"Representation of the operator as a product of other operators.\r\n\r\n        .. math:: O = O_1 O_2 \\dots O_n.\r\n\r\n        Args:\r\n            time_and_coeffs (list[tensor_like or float]): list of coefficients of the Hamiltonian, prepended by the time\r\n                variable\r\n            wires (Any or Iterable[Any]): wires that the operator acts on\r\n            hamiltonian (.Hamiltonian): The commuting Hamiltonian defining the time-evolution operator.\r\n            frequencies (tuple[int or float]): The unique positive differences between eigenvalues in\r\n                the spectrum of the Hamiltonian.\r\n            shifts (tuple[int or float]): The parameter shifts to use in obtaining the\r\n                generalized parameter shift rules. If unspecified, equidistant shifts are used.\r\n\r\n        .. seealso:: :meth:`~.CommutingEvolution.decomposition`.\r\n\r\n        Returns:\r\n            list[.Operator]: decomposition of the operator\r\n        \"\"\"\r\n        # uses standard PauliRot decomposition through ApproxTimeEvolution.\r\n        hamiltonian = qml.Hamiltonian(coeffs, hamiltonian.ops)\r\n        return qml.ApproxTimeEvolution(hamiltonian, time, 1)\r\n\r\n    def adjoint(self):  # pylint: disable=arguments-differ\r\n\r\n        hamiltonian = qml.Hamiltonian(self.parameters[1:], self.hyperparameters[\"hamiltonian\"].ops)\r\n        time = self.parameters[0]\r\n        frequencies = self.hyperparameters[\"frequencies\"]\r\n        shifts = self.hyperparameters[\"shifts\"]\r\n\r\n        return CommutingEvolution(hamiltonian, -time, frequencies, shifts)\r\n", "path": "pennylane/templates/subroutines/commuting_evolution.py"}]}