We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Need a better compilation for swap_to_sqrt_iswap
Right now it uses 4 sqrtiswaps to support arbitrary angle. For a plain ol' `SWAP` (common for routing qubits around) you should be able to get away with 3

```python
        yield cirq.Y(a) ** 0.5
        yield cirq.Y(b) ** 0.5
        yield SQRT_ISWAP(a, b)
        yield cirq.Y(a) ** -0.5
        yield cirq.Y(b) ** -0.5
        yield SQRT_ISWAP(a, b)
        yield cirq.X(a) ** -0.5
        yield cirq.X(b) ** -0.5
        yield SQRT_ISWAP(a, b)
        yield cirq.X(a) ** 0.5
        yield cirq.X(b) ** 0.5
```

should do it.

cc @dstrain115 @john6060 @Strilanc 

--- 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/google/optimizers/convert_to_sqrt_iswap.py`
Content:
```
1 # Copyright 2019 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 from typing import List, Optional, TYPE_CHECKING
15 
16 import numpy as np
17 import sympy
18 
19 from cirq import ops, circuits, protocols
20 
21 if TYPE_CHECKING:
22     import cirq
23 
24 SQRT_ISWAP = ops.ISWAP**0.5
25 SQRT_ISWAP_INV = ops.ISWAP**-0.5
26 
27 
28 # TODO: Combine this with the equivalent functions in google/gate_set.py
29 # Or better yet, write a proper gate set so we don't need this in two places
30 def _near_mod_n(e, t, n, atol=1e-8):
31     return abs((e - t + 1) % n - 1) <= atol
32 
33 
34 def _near_mod_2pi(e, t, atol=1e-8):
35     return _near_mod_n(e, t, 2 * np.pi, atol=atol)
36 
37 
38 class ConvertToSqrtIswapGates(circuits.PointOptimizer):
39     """Attempts to convert gates into ISWAP**-0.5 gates.
40 
41     Since we have Z rotations and arbitrary XY rotations, we
42     can rely on cirq decomposition for one qubit gates and
43     need to only specify special decompositions for two qubit gates.
44 
45     Currently natively specified gates are CZPowGate, ISwapPowGate,
46     and FSimGate.  This will also support gates that decompose into
47     the above gates.
48     """
49 
50     def __init__(self, ignore_failures=False) -> None:
51         """
52         Args:
53             ignore_failures: If set, gates that fail to convert are forwarded
54                 unchanged. If not set, conversion failures raise a TypeError.
55         """
56         super().__init__()
57         self.ignore_failures = ignore_failures
58 
59     def _convert_one(self, op: 'cirq.Operation') -> 'cirq.OP_TREE':
60         """
61         Decomposer intercept:  Let cirq decompose one-qubit gates,
62         intercept on 2-qubit gates if they are known gates.
63         """
64         if isinstance(op, ops.GlobalPhaseOperation):
65             return []
66 
67         gate = op.gate
68 
69         if len(op.qubits) != 2:
70             return NotImplemented
71 
72         q0, q1 = op.qubits
73 
74         if isinstance(gate, ops.CZPowGate):
75             if isinstance(gate.exponent, sympy.Basic):
76                 return cphase_symbols_to_sqrt_iswap(q0, q1, gate.exponent)
77             else:
78                 return cphase_to_sqrt_iswap(q0, q1, gate.exponent)
79         if isinstance(gate, ops.SwapPowGate):
80             return swap_to_sqrt_iswap(q0, q1, gate.exponent)
81         if isinstance(gate, ops.ISwapPowGate):
82             return iswap_to_sqrt_iswap(q0, q1, gate.exponent)
83         if isinstance(gate, ops.FSimGate):
84             return fsim_gate(q0, q1, gate.theta, gate.phi)
85 
86         return NotImplemented
87 
88     def _on_stuck_raise(self, bad):
89         return TypeError(f"Don't know how to work with {bad}. "
90                          "It isn't a native sqrt ISWAP operation, "
91                          "a 1 or 2 qubit gate with a known unitary, "
92                          "or composite.")
93 
94     def convert(self, op: 'cirq.Operation') -> List['cirq.Operation']:
95 
96         a = protocols.decompose(op,
97                                 keep=is_sqrt_iswap_compatible,
98                                 intercepting_decomposer=self._convert_one,
99                                 on_stuck_raise=(None if self.ignore_failures
100                                                 else self._on_stuck_raise))
101         return a
102 
103     def optimization_at(self, circuit, index, op):
104         converted = self.convert(op)
105         if len(converted) == 1 and converted[0] is op:
106             return None
107 
108         return circuits.PointOptimizationSummary(clear_span=1,
109                                                  new_operations=converted,
110                                                  clear_qubits=op.qubits)
111 
112 
113 def is_sqrt_iswap_compatible(op: 'cirq.Operation') -> bool:
114     """Check if the given operation is compatible with the sqrt_iswap gateset
115     gate set.
116 
117     Args:
118         op: Input operation.
119 
120     Returns:
121         True if the operation is native to the gate set, false otherwise.
122     """
123     return is_basic_gate(op.gate) or is_sqrt_iswap(op.gate)
124 
125 
126 def is_sqrt_iswap(gate: Optional['cirq.Gate']) -> bool:
127     """Checks if this is a ± sqrt(iSWAP) gate specified using either
128     ISwapPowGate or with the equivalent FSimGate.
129     """
130     if (isinstance(gate, ops.FSimGate) and
131             not isinstance(gate.theta, sympy.Basic) and
132             _near_mod_2pi(abs(gate.theta), np.pi / 4) and
133             _near_mod_2pi(gate.phi, 0)):
134         return True
135     return (isinstance(gate, ops.ISwapPowGate) and
136             not isinstance(gate.exponent, sympy.Basic) and
137             _near_mod_n(abs(gate.exponent), 0.5, 4))
138 
139 
140 def is_basic_gate(gate: Optional['cirq.Gate']) -> bool:
141     """Check if a gate is a basic supported one-qubit gate.
142 
143         Args:
144             gate: Input gate.
145 
146         Returns:
147             True if the gate is native to the gate set, false otherwise.
148         """
149     return isinstance(gate, (ops.MeasurementGate, ops.PhasedXPowGate,
150                              ops.XPowGate, ops.YPowGate, ops.ZPowGate))
151 
152 
153 def cphase_to_sqrt_iswap(a, b, turns):
154     """Implement a C-Phase gate using two sqrt ISWAP gates and single-qubit
155     operations. The circuit is equivalent to cirq.CZPowGate(exponent=turns).
156 
157     Output unitary:
158     [1   0   0   0],
159     [0   1   0   0],
160     [0   0   1   0],
161     [0   0   0   e^{i turns pi}].
162 
163     Args:
164         a: the first qubit
165         b: the second qubit
166         turns: Exponent specifying the evolution time in number of rotations.
167     """
168     theta = (turns % 2) * np.pi
169     if 0 <= theta <= np.pi:
170         sign = 1.
171         theta_prime = theta
172     elif np.pi < theta < 2 * np.pi:
173         sign = -1.
174         theta_prime = 2 * np.pi - theta
175 
176     if np.isclose(theta, np.pi):
177         # If we are close to pi, just set values manually to avoid possible
178         # numerical errors with arcsin of greater than 1.0 (Ahem, Windows).
179         phi = np.pi / 2
180         xi = np.pi / 2
181     else:
182         phi = np.arcsin(np.sqrt(2) * np.sin(theta_prime / 4))
183         xi = np.arctan(np.tan(phi) / np.sqrt(2))
184 
185     yield ops.rz(sign * 0.5 * theta_prime).on(a)
186     yield ops.rz(sign * 0.5 * theta_prime).on(b)
187     yield ops.rx(xi).on(a)
188     yield ops.X(b)**(-sign * 0.5)
189     yield SQRT_ISWAP_INV(a, b)
190     yield ops.rx(-2 * phi).on(a)
191     yield SQRT_ISWAP(a, b)
192 
193     yield ops.rx(xi).on(a)
194     yield ops.X(b)**(sign * 0.5)
195     # Corrects global phase
196     yield ops.GlobalPhaseOperation(np.exp(sign * theta_prime * 0.25j))
197 
198 
199 def cphase_symbols_to_sqrt_iswap(a, b, turns):
200     """Version of cphase_to_sqrt_iswap that works with symbols.
201 
202     Note that the formulae contained below will need to be flattened
203     into a sweep before serializing.
204     """
205     theta = sympy.Mod(turns, 2.0) * sympy.pi
206 
207     # -1 if theta > pi.  Adds a hacky fudge factor so theta=pi is not 0
208     sign = sympy.sign(sympy.pi - theta + 1e-9)
209 
210     # For sign = 1: theta. For sign = -1, 2pi-theta
211     theta_prime = (sympy.pi - sign * sympy.pi) + sign * theta
212 
213     phi = sympy.asin(np.sqrt(2) * sympy.sin(theta_prime / 4))
214     xi = sympy.atan(sympy.tan(phi) / np.sqrt(2))
215 
216     yield ops.rz(sign * 0.5 * theta_prime).on(a)
217     yield ops.rz(sign * 0.5 * theta_prime).on(b)
218     yield ops.rx(xi).on(a)
219     yield ops.X(b)**(-sign * 0.5)
220     yield SQRT_ISWAP_INV(a, b)
221     yield ops.rx(-2 * phi).on(a)
222     yield SQRT_ISWAP(a, b)
223     yield ops.rx(xi).on(a)
224     yield ops.X(b)**(sign * 0.5)
225 
226 
227 def iswap_to_sqrt_iswap(a, b, turns):
228     """Implement the evolution of the hopping term using two sqrt_iswap gates
229      and single-qubit operations. Output unitary:
230     [1   0   0   0],
231     [0   c  is   0],
232     [0  is   c   0],
233     [0   0   0   1],
234     where c = cos(t * np.pi / 2) and s = sin(t * np.pi / 2).
235 
236     Args:
237         a: the first qubit
238         b: the second qubit
239         t: Exponent that specifies the evolution time in number of rotations.
240     """
241     yield ops.Z(a)**0.75
242     yield ops.Z(b)**0.25
243     yield SQRT_ISWAP_INV(a, b)
244     yield ops.Z(a)**(-turns / 2 + 1)
245     yield ops.Z(b)**(turns / 2)
246     yield SQRT_ISWAP_INV(a, b)
247     yield ops.Z(a)**0.25
248     yield ops.Z(b)**-0.25
249 
250 
251 def swap_to_sqrt_iswap(a, b, turns):
252     """Implement the evolution of the hopping term using two sqrt_iswap gates
253      and single-qubit operations. Output unitary:
254     [[1, 0,        0,     0],
255      [0, g·c,    -i·g·s,  0],
256      [0, -i·g·s,  g·c,    0],
257      [0,   0,      0,     1]]
258      where c = cos(theta) and s = sin(theta).
259         Args:
260             a: the first qubit
261             b: the second qubit
262             theta: The rotational angle that specifies the gate, where
263             c = cos(π·t/2), s = sin(π·t/2), g = exp(i·π·t/2).
264     """
265     yield ops.Z(a)**1.25
266     yield ops.Z(b)**-0.25
267     yield ops.ISWAP(a, b)**-0.5
268     yield ops.Z(a)**(-turns / 2 + 1)
269     yield ops.Z(b)**(turns / 2)
270     yield ops.ISWAP(a, b)**-0.5
271     yield ops.Z(a)**(turns / 2 - 0.25)
272     yield ops.Z(b)**(turns / 2 + 0.25)
273     yield ops.CZ.on(a, b)**(-turns)
274 
275 
276 def fsim_gate(a, b, theta, phi):
277     """FSimGate has a default decomposition in cirq to XXPowGate and YYPowGate,
278     which is an awkward decomposition for this gate set.
279     Decompose into ISWAP and CZ instead."""
280     if theta != 0.0:
281         yield ops.ISWAP(a, b)**(-2 * theta / np.pi)
282     if phi != 0.0:
283         yield ops.CZPowGate(exponent=-phi / np.pi)(a, b)
284
```
--- 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/cirq/google/optimizers/convert_to_sqrt_iswap.py b/cirq/google/optimizers/convert_to_sqrt_iswap.py
--- a/cirq/google/optimizers/convert_to_sqrt_iswap.py
+++ b/cirq/google/optimizers/convert_to_sqrt_iswap.py
@@ -262,6 +262,21 @@
             theta: The rotational angle that specifies the gate, where
             c = cos(π·t/2), s = sin(π·t/2), g = exp(i·π·t/2).
     """
+    if not isinstance(turns, sympy.Basic) and _near_mod_n(turns, 1.0, 2):
+        # Decomposition for cirq.SWAP
+        yield ops.Y(a)**0.5
+        yield ops.Y(b)**0.5
+        yield SQRT_ISWAP(a, b)
+        yield ops.Y(a)**-0.5
+        yield ops.Y(b)**-0.5
+        yield SQRT_ISWAP(a, b)
+        yield ops.X(a)**-0.5
+        yield ops.X(b)**-0.5
+        yield SQRT_ISWAP(a, b)
+        yield ops.X(a)**0.5
+        yield ops.X(b)**0.5
+        return
+
     yield ops.Z(a)**1.25
     yield ops.Z(b)**-0.25
     yield ops.ISWAP(a, b)**-0.5

{"golden_diff": "diff --git a/cirq/google/optimizers/convert_to_sqrt_iswap.py b/cirq/google/optimizers/convert_to_sqrt_iswap.py\n--- a/cirq/google/optimizers/convert_to_sqrt_iswap.py\n+++ b/cirq/google/optimizers/convert_to_sqrt_iswap.py\n@@ -262,6 +262,21 @@\n             theta: The rotational angle that specifies the gate, where\n             c = cos(\u03c0\u00b7t/2), s = sin(\u03c0\u00b7t/2), g = exp(i\u00b7\u03c0\u00b7t/2).\n     \"\"\"\n+    if not isinstance(turns, sympy.Basic) and _near_mod_n(turns, 1.0, 2):\n+        # Decomposition for cirq.SWAP\n+        yield ops.Y(a)**0.5\n+        yield ops.Y(b)**0.5\n+        yield SQRT_ISWAP(a, b)\n+        yield ops.Y(a)**-0.5\n+        yield ops.Y(b)**-0.5\n+        yield SQRT_ISWAP(a, b)\n+        yield ops.X(a)**-0.5\n+        yield ops.X(b)**-0.5\n+        yield SQRT_ISWAP(a, b)\n+        yield ops.X(a)**0.5\n+        yield ops.X(b)**0.5\n+        return\n+\n     yield ops.Z(a)**1.25\n     yield ops.Z(b)**-0.25\n     yield ops.ISWAP(a, b)**-0.5\n", "issue": "Need a better compilation for swap_to_sqrt_iswap\nRight now it uses 4 sqrtiswaps to support arbitrary angle. For a plain ol' `SWAP` (common for routing qubits around) you should be able to get away with 3\r\n\r\n```python\r\n        yield cirq.Y(a) ** 0.5\r\n        yield cirq.Y(b) ** 0.5\r\n        yield SQRT_ISWAP(a, b)\r\n        yield cirq.Y(a) ** -0.5\r\n        yield cirq.Y(b) ** -0.5\r\n        yield SQRT_ISWAP(a, b)\r\n        yield cirq.X(a) ** -0.5\r\n        yield cirq.X(b) ** -0.5\r\n        yield SQRT_ISWAP(a, b)\r\n        yield cirq.X(a) ** 0.5\r\n        yield cirq.X(b) ** 0.5\r\n```\r\n\r\nshould do it.\r\n\r\ncc @dstrain115 @john6060 @Strilanc \n", "before_files": [{"content": "# Copyright 2019 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.\nfrom typing import List, Optional, TYPE_CHECKING\n\nimport numpy as np\nimport sympy\n\nfrom cirq import ops, circuits, protocols\n\nif TYPE_CHECKING:\n    import cirq\n\nSQRT_ISWAP = ops.ISWAP**0.5\nSQRT_ISWAP_INV = ops.ISWAP**-0.5\n\n\n# TODO: Combine this with the equivalent functions in google/gate_set.py\n# Or better yet, write a proper gate set so we don't need this in two places\ndef _near_mod_n(e, t, n, atol=1e-8):\n    return abs((e - t + 1) % n - 1) <= atol\n\n\ndef _near_mod_2pi(e, t, atol=1e-8):\n    return _near_mod_n(e, t, 2 * np.pi, atol=atol)\n\n\nclass ConvertToSqrtIswapGates(circuits.PointOptimizer):\n    \"\"\"Attempts to convert gates into ISWAP**-0.5 gates.\n\n    Since we have Z rotations and arbitrary XY rotations, we\n    can rely on cirq decomposition for one qubit gates and\n    need to only specify special decompositions for two qubit gates.\n\n    Currently natively specified gates are CZPowGate, ISwapPowGate,\n    and FSimGate.  This will also support gates that decompose into\n    the above gates.\n    \"\"\"\n\n    def __init__(self, ignore_failures=False) -> None:\n        \"\"\"\n        Args:\n            ignore_failures: If set, gates that fail to convert are forwarded\n                unchanged. If not set, conversion failures raise a TypeError.\n        \"\"\"\n        super().__init__()\n        self.ignore_failures = ignore_failures\n\n    def _convert_one(self, op: 'cirq.Operation') -> 'cirq.OP_TREE':\n        \"\"\"\n        Decomposer intercept:  Let cirq decompose one-qubit gates,\n        intercept on 2-qubit gates if they are known gates.\n        \"\"\"\n        if isinstance(op, ops.GlobalPhaseOperation):\n            return []\n\n        gate = op.gate\n\n        if len(op.qubits) != 2:\n            return NotImplemented\n\n        q0, q1 = op.qubits\n\n        if isinstance(gate, ops.CZPowGate):\n            if isinstance(gate.exponent, sympy.Basic):\n                return cphase_symbols_to_sqrt_iswap(q0, q1, gate.exponent)\n            else:\n                return cphase_to_sqrt_iswap(q0, q1, gate.exponent)\n        if isinstance(gate, ops.SwapPowGate):\n            return swap_to_sqrt_iswap(q0, q1, gate.exponent)\n        if isinstance(gate, ops.ISwapPowGate):\n            return iswap_to_sqrt_iswap(q0, q1, gate.exponent)\n        if isinstance(gate, ops.FSimGate):\n            return fsim_gate(q0, q1, gate.theta, gate.phi)\n\n        return NotImplemented\n\n    def _on_stuck_raise(self, bad):\n        return TypeError(f\"Don't know how to work with {bad}. \"\n                         \"It isn't a native sqrt ISWAP operation, \"\n                         \"a 1 or 2 qubit gate with a known unitary, \"\n                         \"or composite.\")\n\n    def convert(self, op: 'cirq.Operation') -> List['cirq.Operation']:\n\n        a = protocols.decompose(op,\n                                keep=is_sqrt_iswap_compatible,\n                                intercepting_decomposer=self._convert_one,\n                                on_stuck_raise=(None if self.ignore_failures\n                                                else self._on_stuck_raise))\n        return a\n\n    def optimization_at(self, circuit, index, op):\n        converted = self.convert(op)\n        if len(converted) == 1 and converted[0] is op:\n            return None\n\n        return circuits.PointOptimizationSummary(clear_span=1,\n                                                 new_operations=converted,\n                                                 clear_qubits=op.qubits)\n\n\ndef is_sqrt_iswap_compatible(op: 'cirq.Operation') -> bool:\n    \"\"\"Check if the given operation is compatible with the sqrt_iswap gateset\n    gate set.\n\n    Args:\n        op: Input operation.\n\n    Returns:\n        True if the operation is native to the gate set, false otherwise.\n    \"\"\"\n    return is_basic_gate(op.gate) or is_sqrt_iswap(op.gate)\n\n\ndef is_sqrt_iswap(gate: Optional['cirq.Gate']) -> bool:\n    \"\"\"Checks if this is a \u00b1 sqrt(iSWAP) gate specified using either\n    ISwapPowGate or with the equivalent FSimGate.\n    \"\"\"\n    if (isinstance(gate, ops.FSimGate) and\n            not isinstance(gate.theta, sympy.Basic) and\n            _near_mod_2pi(abs(gate.theta), np.pi / 4) and\n            _near_mod_2pi(gate.phi, 0)):\n        return True\n    return (isinstance(gate, ops.ISwapPowGate) and\n            not isinstance(gate.exponent, sympy.Basic) and\n            _near_mod_n(abs(gate.exponent), 0.5, 4))\n\n\ndef is_basic_gate(gate: Optional['cirq.Gate']) -> bool:\n    \"\"\"Check if a gate is a basic supported one-qubit gate.\n\n        Args:\n            gate: Input gate.\n\n        Returns:\n            True if the gate is native to the gate set, false otherwise.\n        \"\"\"\n    return isinstance(gate, (ops.MeasurementGate, ops.PhasedXPowGate,\n                             ops.XPowGate, ops.YPowGate, ops.ZPowGate))\n\n\ndef cphase_to_sqrt_iswap(a, b, turns):\n    \"\"\"Implement a C-Phase gate using two sqrt ISWAP gates and single-qubit\n    operations. The circuit is equivalent to cirq.CZPowGate(exponent=turns).\n\n    Output unitary:\n    [1   0   0   0],\n    [0   1   0   0],\n    [0   0   1   0],\n    [0   0   0   e^{i turns pi}].\n\n    Args:\n        a: the first qubit\n        b: the second qubit\n        turns: Exponent specifying the evolution time in number of rotations.\n    \"\"\"\n    theta = (turns % 2) * np.pi\n    if 0 <= theta <= np.pi:\n        sign = 1.\n        theta_prime = theta\n    elif np.pi < theta < 2 * np.pi:\n        sign = -1.\n        theta_prime = 2 * np.pi - theta\n\n    if np.isclose(theta, np.pi):\n        # If we are close to pi, just set values manually to avoid possible\n        # numerical errors with arcsin of greater than 1.0 (Ahem, Windows).\n        phi = np.pi / 2\n        xi = np.pi / 2\n    else:\n        phi = np.arcsin(np.sqrt(2) * np.sin(theta_prime / 4))\n        xi = np.arctan(np.tan(phi) / np.sqrt(2))\n\n    yield ops.rz(sign * 0.5 * theta_prime).on(a)\n    yield ops.rz(sign * 0.5 * theta_prime).on(b)\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(-sign * 0.5)\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.rx(-2 * phi).on(a)\n    yield SQRT_ISWAP(a, b)\n\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(sign * 0.5)\n    # Corrects global phase\n    yield ops.GlobalPhaseOperation(np.exp(sign * theta_prime * 0.25j))\n\n\ndef cphase_symbols_to_sqrt_iswap(a, b, turns):\n    \"\"\"Version of cphase_to_sqrt_iswap that works with symbols.\n\n    Note that the formulae contained below will need to be flattened\n    into a sweep before serializing.\n    \"\"\"\n    theta = sympy.Mod(turns, 2.0) * sympy.pi\n\n    # -1 if theta > pi.  Adds a hacky fudge factor so theta=pi is not 0\n    sign = sympy.sign(sympy.pi - theta + 1e-9)\n\n    # For sign = 1: theta. For sign = -1, 2pi-theta\n    theta_prime = (sympy.pi - sign * sympy.pi) + sign * theta\n\n    phi = sympy.asin(np.sqrt(2) * sympy.sin(theta_prime / 4))\n    xi = sympy.atan(sympy.tan(phi) / np.sqrt(2))\n\n    yield ops.rz(sign * 0.5 * theta_prime).on(a)\n    yield ops.rz(sign * 0.5 * theta_prime).on(b)\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(-sign * 0.5)\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.rx(-2 * phi).on(a)\n    yield SQRT_ISWAP(a, b)\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(sign * 0.5)\n\n\ndef iswap_to_sqrt_iswap(a, b, turns):\n    \"\"\"Implement the evolution of the hopping term using two sqrt_iswap gates\n     and single-qubit operations. Output unitary:\n    [1   0   0   0],\n    [0   c  is   0],\n    [0  is   c   0],\n    [0   0   0   1],\n    where c = cos(t * np.pi / 2) and s = sin(t * np.pi / 2).\n\n    Args:\n        a: the first qubit\n        b: the second qubit\n        t: Exponent that specifies the evolution time in number of rotations.\n    \"\"\"\n    yield ops.Z(a)**0.75\n    yield ops.Z(b)**0.25\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.Z(a)**(-turns / 2 + 1)\n    yield ops.Z(b)**(turns / 2)\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.Z(a)**0.25\n    yield ops.Z(b)**-0.25\n\n\ndef swap_to_sqrt_iswap(a, b, turns):\n    \"\"\"Implement the evolution of the hopping term using two sqrt_iswap gates\n     and single-qubit operations. Output unitary:\n    [[1, 0,        0,     0],\n     [0, g\u00b7c,    -i\u00b7g\u00b7s,  0],\n     [0, -i\u00b7g\u00b7s,  g\u00b7c,    0],\n     [0,   0,      0,     1]]\n     where c = cos(theta) and s = sin(theta).\n        Args:\n            a: the first qubit\n            b: the second qubit\n            theta: The rotational angle that specifies the gate, where\n            c = cos(\u03c0\u00b7t/2), s = sin(\u03c0\u00b7t/2), g = exp(i\u00b7\u03c0\u00b7t/2).\n    \"\"\"\n    yield ops.Z(a)**1.25\n    yield ops.Z(b)**-0.25\n    yield ops.ISWAP(a, b)**-0.5\n    yield ops.Z(a)**(-turns / 2 + 1)\n    yield ops.Z(b)**(turns / 2)\n    yield ops.ISWAP(a, b)**-0.5\n    yield ops.Z(a)**(turns / 2 - 0.25)\n    yield ops.Z(b)**(turns / 2 + 0.25)\n    yield ops.CZ.on(a, b)**(-turns)\n\n\ndef fsim_gate(a, b, theta, phi):\n    \"\"\"FSimGate has a default decomposition in cirq to XXPowGate and YYPowGate,\n    which is an awkward decomposition for this gate set.\n    Decompose into ISWAP and CZ instead.\"\"\"\n    if theta != 0.0:\n        yield ops.ISWAP(a, b)**(-2 * theta / np.pi)\n    if phi != 0.0:\n        yield ops.CZPowGate(exponent=-phi / np.pi)(a, b)\n", "path": "cirq/google/optimizers/convert_to_sqrt_iswap.py"}], "after_files": [{"content": "# Copyright 2019 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.\nfrom typing import List, Optional, TYPE_CHECKING\n\nimport numpy as np\nimport sympy\n\nfrom cirq import ops, circuits, protocols\n\nif TYPE_CHECKING:\n    import cirq\n\nSQRT_ISWAP = ops.ISWAP**0.5\nSQRT_ISWAP_INV = ops.ISWAP**-0.5\n\n\n# TODO: Combine this with the equivalent functions in google/gate_set.py\n# Or better yet, write a proper gate set so we don't need this in two places\ndef _near_mod_n(e, t, n, atol=1e-8):\n    return abs((e - t + 1) % n - 1) <= atol\n\n\ndef _near_mod_2pi(e, t, atol=1e-8):\n    return _near_mod_n(e, t, 2 * np.pi, atol=atol)\n\n\nclass ConvertToSqrtIswapGates(circuits.PointOptimizer):\n    \"\"\"Attempts to convert gates into ISWAP**-0.5 gates.\n\n    Since we have Z rotations and arbitrary XY rotations, we\n    can rely on cirq decomposition for one qubit gates and\n    need to only specify special decompositions for two qubit gates.\n\n    Currently natively specified gates are CZPowGate, ISwapPowGate,\n    and FSimGate.  This will also support gates that decompose into\n    the above gates.\n    \"\"\"\n\n    def __init__(self, ignore_failures=False) -> None:\n        \"\"\"\n        Args:\n            ignore_failures: If set, gates that fail to convert are forwarded\n                unchanged. If not set, conversion failures raise a TypeError.\n        \"\"\"\n        super().__init__()\n        self.ignore_failures = ignore_failures\n\n    def _convert_one(self, op: 'cirq.Operation') -> 'cirq.OP_TREE':\n        \"\"\"\n        Decomposer intercept:  Let cirq decompose one-qubit gates,\n        intercept on 2-qubit gates if they are known gates.\n        \"\"\"\n        if isinstance(op, ops.GlobalPhaseOperation):\n            return []\n\n        gate = op.gate\n\n        if len(op.qubits) != 2:\n            return NotImplemented\n\n        q0, q1 = op.qubits\n\n        if isinstance(gate, ops.CZPowGate):\n            if isinstance(gate.exponent, sympy.Basic):\n                return cphase_symbols_to_sqrt_iswap(q0, q1, gate.exponent)\n            else:\n                return cphase_to_sqrt_iswap(q0, q1, gate.exponent)\n        if isinstance(gate, ops.SwapPowGate):\n            return swap_to_sqrt_iswap(q0, q1, gate.exponent)\n        if isinstance(gate, ops.ISwapPowGate):\n            return iswap_to_sqrt_iswap(q0, q1, gate.exponent)\n        if isinstance(gate, ops.FSimGate):\n            return fsim_gate(q0, q1, gate.theta, gate.phi)\n\n        return NotImplemented\n\n    def _on_stuck_raise(self, bad):\n        return TypeError(f\"Don't know how to work with {bad}. \"\n                         \"It isn't a native sqrt ISWAP operation, \"\n                         \"a 1 or 2 qubit gate with a known unitary, \"\n                         \"or composite.\")\n\n    def convert(self, op: 'cirq.Operation') -> List['cirq.Operation']:\n\n        a = protocols.decompose(op,\n                                keep=is_sqrt_iswap_compatible,\n                                intercepting_decomposer=self._convert_one,\n                                on_stuck_raise=(None if self.ignore_failures\n                                                else self._on_stuck_raise))\n        return a\n\n    def optimization_at(self, circuit, index, op):\n        converted = self.convert(op)\n        if len(converted) == 1 and converted[0] is op:\n            return None\n\n        return circuits.PointOptimizationSummary(clear_span=1,\n                                                 new_operations=converted,\n                                                 clear_qubits=op.qubits)\n\n\ndef is_sqrt_iswap_compatible(op: 'cirq.Operation') -> bool:\n    \"\"\"Check if the given operation is compatible with the sqrt_iswap gateset\n    gate set.\n\n    Args:\n        op: Input operation.\n\n    Returns:\n        True if the operation is native to the gate set, false otherwise.\n    \"\"\"\n    return is_basic_gate(op.gate) or is_sqrt_iswap(op.gate)\n\n\ndef is_sqrt_iswap(gate: Optional['cirq.Gate']) -> bool:\n    \"\"\"Checks if this is a \u00b1 sqrt(iSWAP) gate specified using either\n    ISwapPowGate or with the equivalent FSimGate.\n    \"\"\"\n    if (isinstance(gate, ops.FSimGate) and\n            not isinstance(gate.theta, sympy.Basic) and\n            _near_mod_2pi(abs(gate.theta), np.pi / 4) and\n            _near_mod_2pi(gate.phi, 0)):\n        return True\n    return (isinstance(gate, ops.ISwapPowGate) and\n            not isinstance(gate.exponent, sympy.Basic) and\n            _near_mod_n(abs(gate.exponent), 0.5, 4))\n\n\ndef is_basic_gate(gate: Optional['cirq.Gate']) -> bool:\n    \"\"\"Check if a gate is a basic supported one-qubit gate.\n\n        Args:\n            gate: Input gate.\n\n        Returns:\n            True if the gate is native to the gate set, false otherwise.\n        \"\"\"\n    return isinstance(gate, (ops.MeasurementGate, ops.PhasedXPowGate,\n                             ops.XPowGate, ops.YPowGate, ops.ZPowGate))\n\n\ndef cphase_to_sqrt_iswap(a, b, turns):\n    \"\"\"Implement a C-Phase gate using two sqrt ISWAP gates and single-qubit\n    operations. The circuit is equivalent to cirq.CZPowGate(exponent=turns).\n\n    Output unitary:\n    [1   0   0   0],\n    [0   1   0   0],\n    [0   0   1   0],\n    [0   0   0   e^{i turns pi}].\n\n    Args:\n        a: the first qubit\n        b: the second qubit\n        turns: Exponent specifying the evolution time in number of rotations.\n    \"\"\"\n    theta = (turns % 2) * np.pi\n    if 0 <= theta <= np.pi:\n        sign = 1.\n        theta_prime = theta\n    elif np.pi < theta < 2 * np.pi:\n        sign = -1.\n        theta_prime = 2 * np.pi - theta\n\n    if np.isclose(theta, np.pi):\n        # If we are close to pi, just set values manually to avoid possible\n        # numerical errors with arcsin of greater than 1.0 (Ahem, Windows).\n        phi = np.pi / 2\n        xi = np.pi / 2\n    else:\n        phi = np.arcsin(np.sqrt(2) * np.sin(theta_prime / 4))\n        xi = np.arctan(np.tan(phi) / np.sqrt(2))\n\n    yield ops.rz(sign * 0.5 * theta_prime).on(a)\n    yield ops.rz(sign * 0.5 * theta_prime).on(b)\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(-sign * 0.5)\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.rx(-2 * phi).on(a)\n    yield SQRT_ISWAP(a, b)\n\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(sign * 0.5)\n    # Corrects global phase\n    yield ops.GlobalPhaseOperation(np.exp(sign * theta_prime * 0.25j))\n\n\ndef cphase_symbols_to_sqrt_iswap(a, b, turns):\n    \"\"\"Version of cphase_to_sqrt_iswap that works with symbols.\n\n    Note that the formulae contained below will need to be flattened\n    into a sweep before serializing.\n    \"\"\"\n    theta = sympy.Mod(turns, 2.0) * sympy.pi\n\n    # -1 if theta > pi.  Adds a hacky fudge factor so theta=pi is not 0\n    sign = sympy.sign(sympy.pi - theta + 1e-9)\n\n    # For sign = 1: theta. For sign = -1, 2pi-theta\n    theta_prime = (sympy.pi - sign * sympy.pi) + sign * theta\n\n    phi = sympy.asin(np.sqrt(2) * sympy.sin(theta_prime / 4))\n    xi = sympy.atan(sympy.tan(phi) / np.sqrt(2))\n\n    yield ops.rz(sign * 0.5 * theta_prime).on(a)\n    yield ops.rz(sign * 0.5 * theta_prime).on(b)\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(-sign * 0.5)\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.rx(-2 * phi).on(a)\n    yield SQRT_ISWAP(a, b)\n    yield ops.rx(xi).on(a)\n    yield ops.X(b)**(sign * 0.5)\n\n\ndef iswap_to_sqrt_iswap(a, b, turns):\n    \"\"\"Implement the evolution of the hopping term using two sqrt_iswap gates\n     and single-qubit operations. Output unitary:\n    [1   0   0   0],\n    [0   c  is   0],\n    [0  is   c   0],\n    [0   0   0   1],\n    where c = cos(t * np.pi / 2) and s = sin(t * np.pi / 2).\n\n    Args:\n        a: the first qubit\n        b: the second qubit\n        t: Exponent that specifies the evolution time in number of rotations.\n    \"\"\"\n    yield ops.Z(a)**0.75\n    yield ops.Z(b)**0.25\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.Z(a)**(-turns / 2 + 1)\n    yield ops.Z(b)**(turns / 2)\n    yield SQRT_ISWAP_INV(a, b)\n    yield ops.Z(a)**0.25\n    yield ops.Z(b)**-0.25\n\n\ndef swap_to_sqrt_iswap(a, b, turns):\n    \"\"\"Implement the evolution of the hopping term using two sqrt_iswap gates\n     and single-qubit operations. Output unitary:\n    [[1, 0,        0,     0],\n     [0, g\u00b7c,    -i\u00b7g\u00b7s,  0],\n     [0, -i\u00b7g\u00b7s,  g\u00b7c,    0],\n     [0,   0,      0,     1]]\n     where c = cos(theta) and s = sin(theta).\n        Args:\n            a: the first qubit\n            b: the second qubit\n            theta: The rotational angle that specifies the gate, where\n            c = cos(\u03c0\u00b7t/2), s = sin(\u03c0\u00b7t/2), g = exp(i\u00b7\u03c0\u00b7t/2).\n    \"\"\"\n    if not isinstance(turns, sympy.Basic) and _near_mod_n(turns, 1.0, 2):\n        # Decomposition for cirq.SWAP\n        yield ops.Y(a)**0.5\n        yield ops.Y(b)**0.5\n        yield SQRT_ISWAP(a, b)\n        yield ops.Y(a)**-0.5\n        yield ops.Y(b)**-0.5\n        yield SQRT_ISWAP(a, b)\n        yield ops.X(a)**-0.5\n        yield ops.X(b)**-0.5\n        yield SQRT_ISWAP(a, b)\n        yield ops.X(a)**0.5\n        yield ops.X(b)**0.5\n        return\n\n    yield ops.Z(a)**1.25\n    yield ops.Z(b)**-0.25\n    yield ops.ISWAP(a, b)**-0.5\n    yield ops.Z(a)**(-turns / 2 + 1)\n    yield ops.Z(b)**(turns / 2)\n    yield ops.ISWAP(a, b)**-0.5\n    yield ops.Z(a)**(turns / 2 - 0.25)\n    yield ops.Z(b)**(turns / 2 + 0.25)\n    yield ops.CZ.on(a, b)**(-turns)\n\n\ndef fsim_gate(a, b, theta, phi):\n    \"\"\"FSimGate has a default decomposition in cirq to XXPowGate and YYPowGate,\n    which is an awkward decomposition for this gate set.\n    Decompose into ISWAP and CZ instead.\"\"\"\n    if theta != 0.0:\n        yield ops.ISWAP(a, b)**(-2 * theta / np.pi)\n    if phi != 0.0:\n        yield ops.CZPowGate(exponent=-phi / np.pi)(a, b)\n", "path": "cirq/google/optimizers/convert_to_sqrt_iswap.py"}]}