prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Complex numbers can be approximately equal to integers
  but approx_eq incorrectly disagrees
  
  --- 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/protocols/approximate_equality.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 Any, Union
  16 
  17 import numpy as np
  18 
  19 from typing_extensions import Protocol
  20 
  21 
  22 class SupportsApproximateEquality(Protocol):
  23     """Object which can be compared approximately."""
  24 
  25     def _approx_eq_(
  26             self,
  27             other: Any,
  28             *,
  29             atol: Union[int, float]
  30         ) -> bool:
  31         """Approximate comparator.
  32 
  33         Types implementing this protocol define their own logic for approximate
  34         comparison with other types.
  35 
  36         Args:
  37             other: Target object for approximate comparison.
  38             atol: The minimum absolute tolerance. See np.isclose() documentation
  39                   for details.
  40 
  41         Returns:
  42             True if objects are approximately equal, False otherwise. Returns
  43             NotImplemented when approximate equality is not implemented for
  44             given types.
  45         """
  46 
  47 
  48 def approx_eq(val: Any, other: Any, *, atol: Union[int, float] = 1e-8) -> bool:
  49     """Approximately compares two objects.
  50 
  51     If `val` implements SupportsApproxEquality protocol then it is invoked and
  52     takes precedence over all other checks:
  53      - For primitive numeric types `int` and `float` approximate equality is
  54        delegated to math.isclose().
  55      - For complex primitive type the real and imaginary parts are treated
  56        independently and compared using math.isclose().
  57      - For `val` and `other` both iterable of the same length, consecutive
  58        elements are compared recursively. Types of `val` and `other` does not
  59        necessarily needs to match each other. They just need to be iterable and
  60        have the same structure.
  61 
  62     Args:
  63         val: Source object for approximate comparison.
  64         other: Target object for approximate comparison.
  65         atol: The minimum absolute tolerance. See np.isclose() documentation for
  66               details. Defaults to 1e-8 which matches np.isclose() default
  67               absolute tolerance.
  68 
  69     Returns:
  70         True if objects are approximately equal, False otherwise.
  71     """
  72 
  73     # Check if val defines approximate equality via _approx_eq_. This takes
  74     # precedence over all other overloads.
  75     approx_eq_getter = getattr(val, '_approx_eq_', None)
  76     if approx_eq_getter is not None:
  77         result = approx_eq_getter(other, atol)
  78         if result is not NotImplemented:
  79             return result
  80 
  81     # The same for other to make approx_eq symmetric.
  82     other_approx_eq_getter = getattr(other, '_approx_eq_', None)
  83     if other_approx_eq_getter is not None:
  84         result = other_approx_eq_getter(val, atol)
  85         if result is not NotImplemented:
  86             return result
  87 
  88     # Compare primitive types directly.
  89     if isinstance(val, (int, float)):
  90         if not isinstance(other, (int, float)):
  91             return False
  92         return _isclose(val, other, atol=atol)
  93 
  94     if isinstance(val, complex):
  95         if not isinstance(other, complex):
  96             return False
  97         return _isclose(val, other, atol=atol)
  98 
  99     # Try to compare source and target recursively, assuming they're iterable.
  100     result = _approx_eq_iterables(val, other, atol=atol)
  101 
  102     # Fallback to __eq__() when anything else fails.
  103     if result is NotImplemented:
  104         return val == other
  105     return result
  106 
  107 
  108 def _approx_eq_iterables(val: Any, other: Any, *,
  109                          atol: Union[int, float]) -> bool:
  110     """Iterates over arguments and calls approx_eq recursively.
  111 
  112     Types of `val` and `other` does not necessarily needs to match each other.
  113     They just need to be iterable of the same length and have the same
  114     structure, approx_eq() will be called on each consecutive element of `val`
  115     and `other`.
  116 
  117     Args:
  118         val: Source for approximate comparison.
  119         other: Target for approximate comparison.
  120         atol: The minimum absolute tolerance. See np.isclose() documentation for
  121               details.
  122 
  123     Returns:
  124         True if objects are approximately equal, False otherwise. Returns
  125         NotImplemented when approximate equality is not implemented for given
  126         types.
  127     """
  128 
  129     def get_iter(iterable):
  130         try:
  131             return iter(iterable)
  132         except TypeError:
  133             return None
  134 
  135     val_it = get_iter(val)
  136     other_it = get_iter(other)
  137 
  138     if val_it is not None and other_it is not None:
  139         while True:
  140             try:
  141                 val_next = next(val_it)
  142             except StopIteration:
  143                 try:
  144                     next(other_it)
  145                     return False
  146                 except StopIteration:
  147                     return True
  148 
  149             try:
  150                 other_next = next(other_it)
  151             except StopIteration:
  152                 return False
  153 
  154             result = approx_eq(val_next, other_next, atol=atol)
  155             if result is not True:
  156                 return result
  157 
  158     return NotImplemented
  159 
  160 
  161 def _isclose(a: Any, b: Any, *, atol: Union[int, float]) -> bool:
  162     """Convenience wrapper around np.isclose."""
  163     return True if np.isclose([a], [b], atol=atol, rtol=0.0)[0] else False
  164
  ```
  --- 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/protocols/approximate_equality.py b/cirq/protocols/approximate_equality.py
  --- a/cirq/protocols/approximate_equality.py
  +++ b/cirq/protocols/approximate_equality.py
  @@ -13,7 +13,10 @@
   # limitations under the License.
   
   from typing import Any, Union
  +from fractions import Fraction
  +from decimal import Decimal
   
  +import numbers
   import numpy as np
   
   from typing_extensions import Protocol
  @@ -86,15 +89,12 @@
               return result
   
       # Compare primitive types directly.
  -    if isinstance(val, (int, float)):
  -        if not isinstance(other, (int, float)):
  +    if isinstance(val, numbers.Number):
  +        if not isinstance(other, numbers.Number):
               return False
  -        return _isclose(val, other, atol=atol)
  -
  -    if isinstance(val, complex):
  -        if not isinstance(other, complex):
  -            return False
  -        return _isclose(val, other, atol=atol)
  +        result = _isclose(val, other, atol=atol)
  +        if result is not NotImplemented:
  +            return result
   
       # Try to compare source and target recursively, assuming they're iterable.
       result = _approx_eq_iterables(val, other, atol=atol)
  @@ -160,4 +160,19 @@
   
   def _isclose(a: Any, b: Any, *, atol: Union[int, float]) -> bool:
       """Convenience wrapper around np.isclose."""
  -    return True if np.isclose([a], [b], atol=atol, rtol=0.0)[0] else False
  +
  +    # support casting some standard numeric types
  +    x1 = np.asarray([a])
  +    if isinstance(a, (Fraction, Decimal)):
  +        x1 = x1.astype(np.float64)
  +    x2 = np.asarray([b])
  +    if isinstance(b, (Fraction, Decimal)):
  +        x2 = x2.astype(np.float64)
  +
  +    # workaround np.isfinite type limitations. Cast to bool to avoid np.bool_
  +    try:
  +        result = bool(np.isclose(x1, x2, atol=atol, rtol=0.0)[0])
  +    except TypeError:
  +        return NotImplemented
  +
  +    return result
  
verification_info: {"golden_diff": "diff --git a/cirq/protocols/approximate_equality.py b/cirq/protocols/approximate_equality.py\n--- a/cirq/protocols/approximate_equality.py\n+++ b/cirq/protocols/approximate_equality.py\n@@ -13,7 +13,10 @@\n # limitations under the License.\n \n from typing import Any, Union\n+from fractions import Fraction\n+from decimal import Decimal\n \n+import numbers\n import numpy as np\n \n from typing_extensions import Protocol\n@@ -86,15 +89,12 @@\n             return result\n \n     # Compare primitive types directly.\n-    if isinstance(val, (int, float)):\n-        if not isinstance(other, (int, float)):\n+    if isinstance(val, numbers.Number):\n+        if not isinstance(other, numbers.Number):\n             return False\n-        return _isclose(val, other, atol=atol)\n-\n-    if isinstance(val, complex):\n-        if not isinstance(other, complex):\n-            return False\n-        return _isclose(val, other, atol=atol)\n+        result = _isclose(val, other, atol=atol)\n+        if result is not NotImplemented:\n+            return result\n \n     # Try to compare source and target recursively, assuming they're iterable.\n     result = _approx_eq_iterables(val, other, atol=atol)\n@@ -160,4 +160,19 @@\n \n def _isclose(a: Any, b: Any, *, atol: Union[int, float]) -> bool:\n     \"\"\"Convenience wrapper around np.isclose.\"\"\"\n-    return True if np.isclose([a], [b], atol=atol, rtol=0.0)[0] else False\n+\n+    # support casting some standard numeric types\n+    x1 = np.asarray([a])\n+    if isinstance(a, (Fraction, Decimal)):\n+        x1 = x1.astype(np.float64)\n+    x2 = np.asarray([b])\n+    if isinstance(b, (Fraction, Decimal)):\n+        x2 = x2.astype(np.float64)\n+\n+    # workaround np.isfinite type limitations. Cast to bool to avoid np.bool_\n+    try:\n+        result = bool(np.isclose(x1, x2, atol=atol, rtol=0.0)[0])\n+    except TypeError:\n+        return NotImplemented\n+\n+    return result\n", "issue": "Complex numbers can be approximately equal to integers\nbut approx_eq incorrectly disagrees\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 Any, Union\n\nimport numpy as np\n\nfrom typing_extensions import Protocol\n\n\nclass SupportsApproximateEquality(Protocol):\n    \"\"\"Object which can be compared approximately.\"\"\"\n\n    def _approx_eq_(\n            self,\n            other: Any,\n            *,\n            atol: Union[int, float]\n        ) -> bool:\n        \"\"\"Approximate comparator.\n\n        Types implementing this protocol define their own logic for approximate\n        comparison with other types.\n\n        Args:\n            other: Target object for approximate comparison.\n            atol: The minimum absolute tolerance. See np.isclose() documentation\n                  for details.\n\n        Returns:\n            True if objects are approximately equal, False otherwise. Returns\n            NotImplemented when approximate equality is not implemented for\n            given types.\n        \"\"\"\n\n\ndef approx_eq(val: Any, other: Any, *, atol: Union[int, float] = 1e-8) -> bool:\n    \"\"\"Approximately compares two objects.\n\n    If `val` implements SupportsApproxEquality protocol then it is invoked and\n    takes precedence over all other checks:\n     - For primitive numeric types `int` and `float` approximate equality is\n       delegated to math.isclose().\n     - For complex primitive type the real and imaginary parts are treated\n       independently and compared using math.isclose().\n     - For `val` and `other` both iterable of the same length, consecutive\n       elements are compared recursively. Types of `val` and `other` does not\n       necessarily needs to match each other. They just need to be iterable and\n       have the same structure.\n\n    Args:\n        val: Source object for approximate comparison.\n        other: Target object for approximate comparison.\n        atol: The minimum absolute tolerance. See np.isclose() documentation for\n              details. Defaults to 1e-8 which matches np.isclose() default\n              absolute tolerance.\n\n    Returns:\n        True if objects are approximately equal, False otherwise.\n    \"\"\"\n\n    # Check if val defines approximate equality via _approx_eq_. This takes\n    # precedence over all other overloads.\n    approx_eq_getter = getattr(val, '_approx_eq_', None)\n    if approx_eq_getter is not None:\n        result = approx_eq_getter(other, atol)\n        if result is not NotImplemented:\n            return result\n\n    # The same for other to make approx_eq symmetric.\n    other_approx_eq_getter = getattr(other, '_approx_eq_', None)\n    if other_approx_eq_getter is not None:\n        result = other_approx_eq_getter(val, atol)\n        if result is not NotImplemented:\n            return result\n\n    # Compare primitive types directly.\n    if isinstance(val, (int, float)):\n        if not isinstance(other, (int, float)):\n            return False\n        return _isclose(val, other, atol=atol)\n\n    if isinstance(val, complex):\n        if not isinstance(other, complex):\n            return False\n        return _isclose(val, other, atol=atol)\n\n    # Try to compare source and target recursively, assuming they're iterable.\n    result = _approx_eq_iterables(val, other, atol=atol)\n\n    # Fallback to __eq__() when anything else fails.\n    if result is NotImplemented:\n        return val == other\n    return result\n\n\ndef _approx_eq_iterables(val: Any, other: Any, *,\n                         atol: Union[int, float]) -> bool:\n    \"\"\"Iterates over arguments and calls approx_eq recursively.\n\n    Types of `val` and `other` does not necessarily needs to match each other.\n    They just need to be iterable of the same length and have the same\n    structure, approx_eq() will be called on each consecutive element of `val`\n    and `other`.\n\n    Args:\n        val: Source for approximate comparison.\n        other: Target for approximate comparison.\n        atol: The minimum absolute tolerance. See np.isclose() documentation for\n              details.\n\n    Returns:\n        True if objects are approximately equal, False otherwise. Returns\n        NotImplemented when approximate equality is not implemented for given\n        types.\n    \"\"\"\n\n    def get_iter(iterable):\n        try:\n            return iter(iterable)\n        except TypeError:\n            return None\n\n    val_it = get_iter(val)\n    other_it = get_iter(other)\n\n    if val_it is not None and other_it is not None:\n        while True:\n            try:\n                val_next = next(val_it)\n            except StopIteration:\n                try:\n                    next(other_it)\n                    return False\n                except StopIteration:\n                    return True\n\n            try:\n                other_next = next(other_it)\n            except StopIteration:\n                return False\n\n            result = approx_eq(val_next, other_next, atol=atol)\n            if result is not True:\n                return result\n\n    return NotImplemented\n\n\ndef _isclose(a: Any, b: Any, *, atol: Union[int, float]) -> bool:\n    \"\"\"Convenience wrapper around np.isclose.\"\"\"\n    return True if np.isclose([a], [b], atol=atol, rtol=0.0)[0] else False\n", "path": "cirq/protocols/approximate_equality.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 Any, Union\nfrom fractions import Fraction\nfrom decimal import Decimal\n\nimport numbers\nimport numpy as np\n\nfrom typing_extensions import Protocol\n\n\nclass SupportsApproximateEquality(Protocol):\n    \"\"\"Object which can be compared approximately.\"\"\"\n\n    def _approx_eq_(\n            self,\n            other: Any,\n            *,\n            atol: Union[int, float]\n        ) -> bool:\n        \"\"\"Approximate comparator.\n\n        Types implementing this protocol define their own logic for approximate\n        comparison with other types.\n\n        Args:\n            other: Target object for approximate comparison.\n            atol: The minimum absolute tolerance. See np.isclose() documentation\n                  for details.\n\n        Returns:\n            True if objects are approximately equal, False otherwise. Returns\n            NotImplemented when approximate equality is not implemented for\n            given types.\n        \"\"\"\n\n\ndef approx_eq(val: Any, other: Any, *, atol: Union[int, float] = 1e-8) -> bool:\n    \"\"\"Approximately compares two objects.\n\n    If `val` implements SupportsApproxEquality protocol then it is invoked and\n    takes precedence over all other checks:\n     - For primitive numeric types `int` and `float` approximate equality is\n       delegated to math.isclose().\n     - For complex primitive type the real and imaginary parts are treated\n       independently and compared using math.isclose().\n     - For `val` and `other` both iterable of the same length, consecutive\n       elements are compared recursively. Types of `val` and `other` does not\n       necessarily needs to match each other. They just need to be iterable and\n       have the same structure.\n\n    Args:\n        val: Source object for approximate comparison.\n        other: Target object for approximate comparison.\n        atol: The minimum absolute tolerance. See np.isclose() documentation for\n              details. Defaults to 1e-8 which matches np.isclose() default\n              absolute tolerance.\n\n    Returns:\n        True if objects are approximately equal, False otherwise.\n    \"\"\"\n\n    # Check if val defines approximate equality via _approx_eq_. This takes\n    # precedence over all other overloads.\n    approx_eq_getter = getattr(val, '_approx_eq_', None)\n    if approx_eq_getter is not None:\n        result = approx_eq_getter(other, atol)\n        if result is not NotImplemented:\n            return result\n\n    # The same for other to make approx_eq symmetric.\n    other_approx_eq_getter = getattr(other, '_approx_eq_', None)\n    if other_approx_eq_getter is not None:\n        result = other_approx_eq_getter(val, atol)\n        if result is not NotImplemented:\n            return result\n\n    # Compare primitive types directly.\n    if isinstance(val, numbers.Number):\n        if not isinstance(other, numbers.Number):\n            return False\n        result = _isclose(val, other, atol=atol)\n        if result is not NotImplemented:\n            return result\n\n    # Try to compare source and target recursively, assuming they're iterable.\n    result = _approx_eq_iterables(val, other, atol=atol)\n\n    # Fallback to __eq__() when anything else fails.\n    if result is NotImplemented:\n        return val == other\n    return result\n\n\ndef _approx_eq_iterables(val: Any, other: Any, *,\n                         atol: Union[int, float]) -> bool:\n    \"\"\"Iterates over arguments and calls approx_eq recursively.\n\n    Types of `val` and `other` does not necessarily needs to match each other.\n    They just need to be iterable of the same length and have the same\n    structure, approx_eq() will be called on each consecutive element of `val`\n    and `other`.\n\n    Args:\n        val: Source for approximate comparison.\n        other: Target for approximate comparison.\n        atol: The minimum absolute tolerance. See np.isclose() documentation for\n              details.\n\n    Returns:\n        True if objects are approximately equal, False otherwise. Returns\n        NotImplemented when approximate equality is not implemented for given\n        types.\n    \"\"\"\n\n    def get_iter(iterable):\n        try:\n            return iter(iterable)\n        except TypeError:\n            return None\n\n    val_it = get_iter(val)\n    other_it = get_iter(other)\n\n    if val_it is not None and other_it is not None:\n        while True:\n            try:\n                val_next = next(val_it)\n            except StopIteration:\n                try:\n                    next(other_it)\n                    return False\n                except StopIteration:\n                    return True\n\n            try:\n                other_next = next(other_it)\n            except StopIteration:\n                return False\n\n            result = approx_eq(val_next, other_next, atol=atol)\n            if result is not True:\n                return result\n\n    return NotImplemented\n\n\ndef _isclose(a: Any, b: Any, *, atol: Union[int, float]) -> bool:\n    \"\"\"Convenience wrapper around np.isclose.\"\"\"\n\n    # support casting some standard numeric types\n    x1 = np.asarray([a])\n    if isinstance(a, (Fraction, Decimal)):\n        x1 = x1.astype(np.float64)\n    x2 = np.asarray([b])\n    if isinstance(b, (Fraction, Decimal)):\n        x2 = x2.astype(np.float64)\n\n    # workaround np.isfinite type limitations. Cast to bool to avoid np.bool_\n    try:\n        result = bool(np.isclose(x1, x2, atol=atol, rtol=0.0)[0])\n    except TypeError:\n        return NotImplemented\n\n    return result\n", "path": "cirq/protocols/approximate_equality.py"}]}