prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Add `_phase_by_` magic method to `ControlledGate`
  Comes after https://github.com/quantumlib/Cirq/issues/947
  
  The logic is as follows: if the qubit index is 0 (the control), the operation is returned unchanged. If it is larger then we delegate to phasing the sub gate with `cirq.phase_by` and a default result of NotImplemented. If it's NotImplemented, we return NotImplemented. Otherwise we return a controlled gate with the phased sub gate.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `cirq/ops/controlled_gate.py`
  Content:
  ```
  1 # Copyright 2018 The Cirq Developers
  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 #     https://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 from typing import Union, Sequence, Any
  16 
  17 import numpy as np
  18 
  19 from cirq import linalg, protocols
  20 from cirq.ops import raw_types
  21 from cirq.type_workarounds import NotImplementedType
  22 
  23 
  24 class ControlledGate(raw_types.Gate):
  25     """Augments existing gates with a control qubit."""
  26 
  27     def __init__(self, sub_gate: raw_types.Gate) -> None:
  28         """Initializes the controlled gate.
  29 
  30         Args:
  31             sub_gate: The gate to add a control qubit to.
  32             default_extensions: The extensions method that should be used when
  33                 determining if the controlled gate supports certain gate
  34                 features. For example, if this extensions instance is able to
  35                 cast sub_gate to a ExtrapolatableEffect then the controlled gate
  36                 can also be cast to a ExtrapolatableEffect. When this value is
  37                 None, an empty extensions instance is used instead.
  38         """
  39         self.sub_gate = sub_gate
  40 
  41     def validate_args(self, qubits) -> None:
  42         if len(qubits) < 1:
  43             raise ValueError('No control qubit specified.')
  44         self.sub_gate.validate_args(qubits[1:])
  45 
  46     def __eq__(self, other):
  47         if not isinstance(other, type(self)):
  48             return NotImplemented
  49         return self.sub_gate == other.sub_gate
  50 
  51     def __ne__(self, other):
  52         return not self == other
  53 
  54     def __hash__(self):
  55         return hash((ControlledGate, self.sub_gate))
  56 
  57     def _apply_unitary_to_tensor_(self,
  58                                   target_tensor: np.ndarray,
  59                                   available_buffer: np.ndarray,
  60                                   axes: Sequence[int],
  61                                   ) -> np.ndarray:
  62         control = axes[0]
  63         rest = axes[1:]
  64         active = linalg.slice_for_qubits_equal_to([control], 1)
  65         sub_axes = [r - int(r > control) for r in rest]
  66         target_view = target_tensor[active]
  67         buffer_view = available_buffer[active]
  68         result = protocols.apply_unitary_to_tensor(
  69             self.sub_gate,
  70             target_view,
  71             buffer_view,
  72             sub_axes,
  73             default=NotImplemented)
  74 
  75         if result is NotImplemented:
  76             return NotImplemented
  77 
  78         if result is target_view:
  79             return target_tensor
  80 
  81         if result is buffer_view:
  82             inactive = linalg.slice_for_qubits_equal_to([control], 0)
  83             available_buffer[inactive] = target_tensor[inactive]
  84             return available_buffer
  85 
  86         # HACK: assume they didn't somehow escape the slice view and edit the
  87         # rest of target_tensor.
  88         target_tensor[active] = result
  89         return target_tensor
  90 
  91     def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:
  92         sub_matrix = protocols.unitary(self.sub_gate, None)
  93         if sub_matrix is None:
  94             return NotImplemented
  95         return linalg.block_diag(np.eye(sub_matrix.shape[0]), sub_matrix)
  96 
  97     def __pow__(self, exponent: Any) -> 'ControlledGate':
  98         new_sub_gate = protocols.pow(self.sub_gate,
  99                                      exponent,
  100                                      NotImplemented)
  101         if new_sub_gate is NotImplemented:
  102             return NotImplemented
  103         return ControlledGate(new_sub_gate)
  104 
  105     def _is_parameterized_(self):
  106         return protocols.is_parameterized(self.sub_gate)
  107 
  108     def _resolve_parameters_(self, param_resolver):
  109         new_sub_gate = protocols.resolve_parameters(self.sub_gate,
  110                                                     param_resolver)
  111         return ControlledGate(new_sub_gate)
  112 
  113     def _trace_distance_bound_(self):
  114         return protocols.trace_distance_bound(self.sub_gate)
  115 
  116     def _circuit_diagram_info_(self,
  117                                args: protocols.CircuitDiagramInfoArgs
  118                                ) -> protocols.CircuitDiagramInfo:
  119         sub_info = protocols.circuit_diagram_info(self.sub_gate, args, None)
  120         if sub_info is None:
  121             return NotImplemented
  122         return protocols.CircuitDiagramInfo(
  123             wire_symbols=('@',) + sub_info.wire_symbols,
  124             exponent=sub_info.exponent)
  125 
  126     def __str__(self):
  127         return 'C' + str(self.sub_gate)
  128 
  129     def __repr__(self):
  130         return 'cirq.ControlledGate(sub_gate={!r})'.format(self.sub_gate)
  131
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/cirq/ops/controlled_gate.py b/cirq/ops/controlled_gate.py
  --- a/cirq/ops/controlled_gate.py
  +++ b/cirq/ops/controlled_gate.py
  @@ -29,12 +29,6 @@
   
           Args:
               sub_gate: The gate to add a control qubit to.
  -            default_extensions: The extensions method that should be used when
  -                determining if the controlled gate supports certain gate
  -                features. For example, if this extensions instance is able to
  -                cast sub_gate to a ExtrapolatableEffect then the controlled gate
  -                can also be cast to a ExtrapolatableEffect. When this value is
  -                None, an empty extensions instance is used instead.
           """
           self.sub_gate = sub_gate
   
  @@ -102,6 +96,15 @@
               return NotImplemented
           return ControlledGate(new_sub_gate)
   
  +    def _phase_by_(self, phase_turns: float, qubit_index: int):
  +        if qubit_index == 0:
  +            return self
  +        phased_gate = protocols.phase_by(
  +            self.sub_gate, phase_turns, qubit_index-1, None)
  +        if phased_gate is None:
  +            return NotImplemented
  +        return ControlledGate(phased_gate)
  +
       def _is_parameterized_(self):
           return protocols.is_parameterized(self.sub_gate)
  
verification_info: {"golden_diff": "diff --git a/cirq/ops/controlled_gate.py b/cirq/ops/controlled_gate.py\n--- a/cirq/ops/controlled_gate.py\n+++ b/cirq/ops/controlled_gate.py\n@@ -29,12 +29,6 @@\n \n         Args:\n             sub_gate: The gate to add a control qubit to.\n-            default_extensions: The extensions method that should be used when\n-                determining if the controlled gate supports certain gate\n-                features. For example, if this extensions instance is able to\n-                cast sub_gate to a ExtrapolatableEffect then the controlled gate\n-                can also be cast to a ExtrapolatableEffect. When this value is\n-                None, an empty extensions instance is used instead.\n         \"\"\"\n         self.sub_gate = sub_gate\n \n@@ -102,6 +96,15 @@\n             return NotImplemented\n         return ControlledGate(new_sub_gate)\n \n+    def _phase_by_(self, phase_turns: float, qubit_index: int):\n+        if qubit_index == 0:\n+            return self\n+        phased_gate = protocols.phase_by(\n+            self.sub_gate, phase_turns, qubit_index-1, None)\n+        if phased_gate is None:\n+            return NotImplemented\n+        return ControlledGate(phased_gate)\n+\n     def _is_parameterized_(self):\n         return protocols.is_parameterized(self.sub_gate)\n", "issue": "Add `_phase_by_` magic method to `ControlledGate`\nComes after https://github.com/quantumlib/Cirq/issues/947\r\n\r\nThe logic is as follows: if the qubit index is 0 (the control), the operation is returned unchanged. If it is larger then we delegate to phasing the sub gate with `cirq.phase_by` and a default result of NotImplemented. If it's NotImplemented, we return NotImplemented. Otherwise we return a controlled gate with the phased sub gate.\n", "before_files": [{"content": "# Copyright 2018 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom typing import Union, Sequence, Any\n\nimport numpy as np\n\nfrom cirq import linalg, protocols\nfrom cirq.ops import raw_types\nfrom cirq.type_workarounds import NotImplementedType\n\n\nclass ControlledGate(raw_types.Gate):\n    \"\"\"Augments existing gates with a control qubit.\"\"\"\n\n    def __init__(self, sub_gate: raw_types.Gate) -> None:\n        \"\"\"Initializes the controlled gate.\n\n        Args:\n            sub_gate: The gate to add a control qubit to.\n            default_extensions: The extensions method that should be used when\n                determining if the controlled gate supports certain gate\n                features. For example, if this extensions instance is able to\n                cast sub_gate to a ExtrapolatableEffect then the controlled gate\n                can also be cast to a ExtrapolatableEffect. When this value is\n                None, an empty extensions instance is used instead.\n        \"\"\"\n        self.sub_gate = sub_gate\n\n    def validate_args(self, qubits) -> None:\n        if len(qubits) < 1:\n            raise ValueError('No control qubit specified.')\n        self.sub_gate.validate_args(qubits[1:])\n\n    def __eq__(self, other):\n        if not isinstance(other, type(self)):\n            return NotImplemented\n        return self.sub_gate == other.sub_gate\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        return hash((ControlledGate, self.sub_gate))\n\n    def _apply_unitary_to_tensor_(self,\n                                  target_tensor: np.ndarray,\n                                  available_buffer: np.ndarray,\n                                  axes: Sequence[int],\n                                  ) -> np.ndarray:\n        control = axes[0]\n        rest = axes[1:]\n        active = linalg.slice_for_qubits_equal_to([control], 1)\n        sub_axes = [r - int(r > control) for r in rest]\n        target_view = target_tensor[active]\n        buffer_view = available_buffer[active]\n        result = protocols.apply_unitary_to_tensor(\n            self.sub_gate,\n            target_view,\n            buffer_view,\n            sub_axes,\n            default=NotImplemented)\n\n        if result is NotImplemented:\n            return NotImplemented\n\n        if result is target_view:\n            return target_tensor\n\n        if result is buffer_view:\n            inactive = linalg.slice_for_qubits_equal_to([control], 0)\n            available_buffer[inactive] = target_tensor[inactive]\n            return available_buffer\n\n        # HACK: assume they didn't somehow escape the slice view and edit the\n        # rest of target_tensor.\n        target_tensor[active] = result\n        return target_tensor\n\n    def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:\n        sub_matrix = protocols.unitary(self.sub_gate, None)\n        if sub_matrix is None:\n            return NotImplemented\n        return linalg.block_diag(np.eye(sub_matrix.shape[0]), sub_matrix)\n\n    def __pow__(self, exponent: Any) -> 'ControlledGate':\n        new_sub_gate = protocols.pow(self.sub_gate,\n                                     exponent,\n                                     NotImplemented)\n        if new_sub_gate is NotImplemented:\n            return NotImplemented\n        return ControlledGate(new_sub_gate)\n\n    def _is_parameterized_(self):\n        return protocols.is_parameterized(self.sub_gate)\n\n    def _resolve_parameters_(self, param_resolver):\n        new_sub_gate = protocols.resolve_parameters(self.sub_gate,\n                                                    param_resolver)\n        return ControlledGate(new_sub_gate)\n\n    def _trace_distance_bound_(self):\n        return protocols.trace_distance_bound(self.sub_gate)\n\n    def _circuit_diagram_info_(self,\n                               args: protocols.CircuitDiagramInfoArgs\n                               ) -> protocols.CircuitDiagramInfo:\n        sub_info = protocols.circuit_diagram_info(self.sub_gate, args, None)\n        if sub_info is None:\n            return NotImplemented\n        return protocols.CircuitDiagramInfo(\n            wire_symbols=('@',) + sub_info.wire_symbols,\n            exponent=sub_info.exponent)\n\n    def __str__(self):\n        return 'C' + str(self.sub_gate)\n\n    def __repr__(self):\n        return 'cirq.ControlledGate(sub_gate={!r})'.format(self.sub_gate)\n", "path": "cirq/ops/controlled_gate.py"}], "after_files": [{"content": "# Copyright 2018 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom typing import Union, Sequence, Any\n\nimport numpy as np\n\nfrom cirq import linalg, protocols\nfrom cirq.ops import raw_types\nfrom cirq.type_workarounds import NotImplementedType\n\n\nclass ControlledGate(raw_types.Gate):\n    \"\"\"Augments existing gates with a control qubit.\"\"\"\n\n    def __init__(self, sub_gate: raw_types.Gate) -> None:\n        \"\"\"Initializes the controlled gate.\n\n        Args:\n            sub_gate: The gate to add a control qubit to.\n        \"\"\"\n        self.sub_gate = sub_gate\n\n    def validate_args(self, qubits) -> None:\n        if len(qubits) < 1:\n            raise ValueError('No control qubit specified.')\n        self.sub_gate.validate_args(qubits[1:])\n\n    def __eq__(self, other):\n        if not isinstance(other, type(self)):\n            return NotImplemented\n        return self.sub_gate == other.sub_gate\n\n    def __ne__(self, other):\n        return not self == other\n\n    def __hash__(self):\n        return hash((ControlledGate, self.sub_gate))\n\n    def _apply_unitary_to_tensor_(self,\n                                  target_tensor: np.ndarray,\n                                  available_buffer: np.ndarray,\n                                  axes: Sequence[int],\n                                  ) -> np.ndarray:\n        control = axes[0]\n        rest = axes[1:]\n        active = linalg.slice_for_qubits_equal_to([control], 1)\n        sub_axes = [r - int(r > control) for r in rest]\n        target_view = target_tensor[active]\n        buffer_view = available_buffer[active]\n        result = protocols.apply_unitary_to_tensor(\n            self.sub_gate,\n            target_view,\n            buffer_view,\n            sub_axes,\n            default=NotImplemented)\n\n        if result is NotImplemented:\n            return NotImplemented\n\n        if result is target_view:\n            return target_tensor\n\n        if result is buffer_view:\n            inactive = linalg.slice_for_qubits_equal_to([control], 0)\n            available_buffer[inactive] = target_tensor[inactive]\n            return available_buffer\n\n        # HACK: assume they didn't somehow escape the slice view and edit the\n        # rest of target_tensor.\n        target_tensor[active] = result\n        return target_tensor\n\n    def _unitary_(self) -> Union[np.ndarray, NotImplementedType]:\n        sub_matrix = protocols.unitary(self.sub_gate, None)\n        if sub_matrix is None:\n            return NotImplemented\n        return linalg.block_diag(np.eye(sub_matrix.shape[0]), sub_matrix)\n\n    def __pow__(self, exponent: Any) -> 'ControlledGate':\n        new_sub_gate = protocols.pow(self.sub_gate,\n                                     exponent,\n                                     NotImplemented)\n        if new_sub_gate is NotImplemented:\n            return NotImplemented\n        return ControlledGate(new_sub_gate)\n\n    def _phase_by_(self, phase_turns: float, qubit_index: int):\n        if qubit_index == 0:\n            return self\n        phased_gate = protocols.phase_by(\n            self.sub_gate, phase_turns, qubit_index-1, None)\n        if phased_gate is None:\n            return NotImplemented\n        return ControlledGate(phased_gate)\n\n    def _is_parameterized_(self):\n        return protocols.is_parameterized(self.sub_gate)\n\n    def _resolve_parameters_(self, param_resolver):\n        new_sub_gate = protocols.resolve_parameters(self.sub_gate,\n                                                    param_resolver)\n        return ControlledGate(new_sub_gate)\n\n    def _trace_distance_bound_(self):\n        return protocols.trace_distance_bound(self.sub_gate)\n\n    def _circuit_diagram_info_(self,\n                               args: protocols.CircuitDiagramInfoArgs\n                               ) -> protocols.CircuitDiagramInfo:\n        sub_info = protocols.circuit_diagram_info(self.sub_gate, args, None)\n        if sub_info is None:\n            return NotImplemented\n        return protocols.CircuitDiagramInfo(\n            wire_symbols=('@',) + sub_info.wire_symbols,\n            exponent=sub_info.exponent)\n\n    def __str__(self):\n        return 'C' + str(self.sub_gate)\n\n    def __repr__(self):\n        return 'cirq.ControlledGate(sub_gate={!r})'.format(self.sub_gate)\n", "path": "cirq/ops/controlled_gate.py"}]}