internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: quantumlib/Cirq

Issue:
SupportsPauliExpansion Protocol isn't defined
For consistency with the other protocols, shouldn't we have a Protocol that has the method `_pauli_expansion_`? @viathor 


Discussion:

Resolving patch:
diff --git a/cirq/__init__.py b/cirq/__init__.py
--- a/cirq/__init__.py
+++ b/cirq/__init__.py
@@ -479,6 +479,7 @@
     SupportsMeasurementKey,
     SupportsMixture,
     SupportsParameterization,
+    SupportsPauliExpansion,
     SupportsPhase,
     SupportsQasm,
     SupportsQasmWithArgs,
diff --git a/cirq/protocols/__init__.py b/cirq/protocols/__init__.py
--- a/cirq/protocols/__init__.py
+++ b/cirq/protocols/__init__.py
@@ -98,7 +98,9 @@
 from cirq.protocols.mul_protocol import (
     mul,)
 from cirq.protocols.pauli_expansion_protocol import (
-    pauli_expansion,)
+    pauli_expansion,
+    SupportsPauliExpansion,
+)
 # pylint: disable=redefined-builtin
 from cirq.protocols.pow_protocol import (
     pow,)
diff --git a/cirq/protocols/pauli_expansion_protocol.py b/cirq/protocols/pauli_expansion_protocol.py
--- a/cirq/protocols/pauli_expansion_protocol.py
+++ b/cirq/protocols/pauli_expansion_protocol.py
@@ -14,6 +14,7 @@
 """Protocol for obtaining expansion of linear operators in Pauli basis."""
 
 from typing import Any, TypeVar, Union
+from typing_extensions import Protocol
 
 from cirq import value
 from cirq.linalg import operator_spaces
@@ -25,6 +26,20 @@
                               )  # type: value.LinearDict[str]
 
 
+class SupportsPauliExpansion(Protocol):
+    """An object that knows its expansion in the Pauli basis."""
+
+    def _pauli_expansion_(self) -> value.LinearDict[str]:
+        """Efficiently obtains expansion of self in the Pauli basis.
+
+        Returns:
+            Linear dict keyed by name of Pauli basis element. The names
+            consist of n captal letters from the set 'I', 'X', 'Y', 'Z'
+            where n is the number of qubits. For example, 'II', 'IX' and
+            'XY' are valid Pauli names in the two-qubit case.
+        """
+
+
 def pauli_expansion(
         val: Any,
         *,


Test patch:
diff --git a/cirq/protocols/json_serialization_test.py b/cirq/protocols/json_serialization_test.py
--- a/cirq/protocols/json_serialization_test.py
+++ b/cirq/protocols/json_serialization_test.py
@@ -167,6 +167,7 @@ def test_fail_to_resolve():
     'SupportsMeasurementKey',
     'SupportsMixture',
     'SupportsParameterization',
+    'SupportsPauliExpansion',
     'SupportsPhase',
     'SupportsQasm',
     'SupportsQasmWithArgs',
Repository: quantumlib/Cirq

Issue:
Discrepancy in __iadd__ vs. __add__
**Description of the issue**
Adding gates to circuits behaves differently when using `circuit + gate` vs. `circuit += gate`.
It's not immediately clear which one of these behaves "correctly". Related issue: #3246.

**How to reproduce the issue**
```
    a = cirq.NamedQubit('alice')
    b = cirq.NamedQubit('bob')
    c = cirq.Circuit(
        cirq.Moment(cirq.H(a), cirq.X(b)),
        cirq.Moment(cirq.X(a)),
    )
    g = cirq.H(b)

    cg = cirq.Circuit(c)
    cg += g

    # FAILS
    assert cg == c + g
```

<details>
cg (result of +=):

```
alice: ───H───X───

bob: ─────X───H───
```

c + g:
```
alice: ───H───X───────

bob: ─────X───────H───
```
</details>

**Cirq version**
0.9.0.dev


Discussion:

Resolving patch:
diff --git a/cirq/circuits/circuit.py b/cirq/circuits/circuit.py
--- a/cirq/circuits/circuit.py
+++ b/cirq/circuits/circuit.py
@@ -262,18 +262,14 @@ def __iadd__(self, other):
         return self
 
     def __add__(self, other):
-        if not isinstance(other, type(self)):
-            if not isinstance(other, (ops.Operation, Iterable)):
-                return NotImplemented
-            # Auto wrap OP_TREE inputs into a circuit.
-            other = Circuit(other)
-
-        device = (self._device if other.device is devices.UNCONSTRAINED_DEVICE
-                  else other.device)
-        device_2 = (other.device if self._device is devices.UNCONSTRAINED_DEVICE
-                    else self._device)
-        if device != device_2:
-            raise ValueError("Can't add circuits with incompatible devices.")
+        if isinstance(other, type(self)):
+            if (devices.UNCONSTRAINED_DEVICE not in [
+                    self._device, other.device
+            ] and self._device != other.device):
+                raise ValueError(
+                    "Can't add circuits with incompatible devices.")
+        elif not isinstance(other, (ops.Operation, Iterable)):
+            return NotImplemented
 
         result = self.copy()
         return result.__iadd__(other)


Test patch:
diff --git a/cirq/circuits/circuit_test.py b/cirq/circuits/circuit_test.py
--- a/cirq/circuits/circuit_test.py
+++ b/cirq/circuits/circuit_test.py
@@ -268,6 +268,15 @@ def test_radd_op_tree():
         _ = [cirq.X(cirq.NamedQubit('a'))] + c
 
 
+def test_add_iadd_equivalence():
+    q0, q1 = cirq.LineQubit.range(2)
+    iadd_circuit = cirq.Circuit(cirq.X(q0))
+    iadd_circuit += cirq.H(q1)
+
+    add_circuit = cirq.Circuit(cirq.X(q0)) + cirq.H(q1)
+    assert iadd_circuit == add_circuit
+
+
 def test_bool():
     assert not cirq.Circuit()
     assert cirq.Circuit(cirq.X(cirq.NamedQubit('a')))
Repository: quantumlib/Cirq

Issue:
_BGate defined as complex conjugate of B gate
The B gate class in two_qubit_to_fsim.py appears to have been defined as the complex conjugate of the B gate as defined in the original reference (unless I'm making a sign error somewhere). It should be `XX(a, b)**-0.5, YY(a, b)**-0.25`,

https://github.com/quantumlib/Cirq/blob/2b88d34dc2c4dc5dc1c59d21810114112286c225/cirq/optimizers/two_qubit_to_fsim.py#L137

https://arxiv.org/abs/quant-ph/0312193

In a sense this doesn't really matter, since _BGate is only used internally to the module, and B and its conjugate are related by 1-qubit gates. But it might trip someone up down the line. 



Discussion:
I think you're right, thank you for pointing it out!!
The `XX` gate is defined as <img src="https://render.githubusercontent.com/render/math?math=e%5E%7B-i%20%5Cpi%20%2F2%20%5Csigma_x%5E%7B(1)%7D%20%5Csigma_x%5E%7B(2)%7D%7D"> and implemented as such in our `XPowGate`. And `YY` is similar. I suspect that for the 2qubit decomposition work to FSim it still worked because of some symmetry. However just simply changing the decomposition to the other direction, it breaks all the tests. 

@viathor can you confirm our understanding here? 
@balopat @gecrooks I agree that cirq's _BGate is the complex conjugate of B gate defined in the paper.

I think the decomposition works because the inverse B gate is locally equivalent to the B gate (e.g. conjugate by ZI), though I think some angles on the single-qubit gates may need adjustment.

We should fix this.

@gecrooks Thank you for catching this! Would you like to have a go at the fix?

Resolving patch:
diff --git a/cirq/optimizers/two_qubit_to_fsim.py b/cirq/optimizers/two_qubit_to_fsim.py
--- a/cirq/optimizers/two_qubit_to_fsim.py
+++ b/cirq/optimizers/two_qubit_to_fsim.py
@@ -169,8 +169,8 @@ def num_qubits(self) -> int:
     def _decompose_(self, qubits):
         a, b = qubits
         return [
-            ops.XX(a, b)**0.5,
-            ops.YY(a, b)**0.25,
+            ops.XX(a, b)**-0.5,
+            ops.YY(a, b)**-0.25,
         ]
 
 
@@ -231,9 +231,9 @@ def _decompose_interaction_into_two_b_gates_ignoring_single_qubit_ops(
         b2 = np.arcsin(np.sqrt(b1))
         b3 = np.arccos(1 - 4 * r)
         rb = [
-            ops.rz(b2).on(b),
-            ops.ry(b3).on(b),
-            ops.rz(b2).on(b),
+            ops.rz(-b2).on(b),
+            ops.ry(-b3).on(b),
+            ops.rz(-b2).on(b),
         ]
     s = 1 if z < 0 else -1
     return [


Test patch:
Repository: quantumlib/Cirq

Issue:
cirq.contrib.quimb fails with quimb 1.2.0
**Description of the issue**

Quimb fails with version 1.2.0.  We should either require 1.3 or (ideally) fix whatever was broken in 1.2


**How to reproduce the issue**
```
pip install quimb==1.2.0
pytest cirq/contrib/quimb/
```

<details>
test_tensor_expectation_value
...
 AttributeError: 'numpy.complex128' object has no attribute 'add_owner'
</details>

**Cirq version**
cirq from HEAD and quimb == 1.2.0



Discussion:
It fails in `rank_simplify`. I think the fix is this line: https://github.com/jcmgray/quimb/commit/492201519157355b751d64af73e297a318f0adff#diff-382c633ca92381427ca0bc74c1ac3081R3361 (line 3361 of tensor_core)

One option is to comment out `state_vector.py:150` which calls `rank_simplify`. It's possible EITHER that (1) this will cause performance to deteriorate in a major way for gridlike circuits because lots of things can be fused ahead of any true contraction OR (2) `contract` already finds a path that does this so it's fine.

Instead of truly investigating this, I say we set the requirements to `>=1.3.0` and if someone is desperate to use `1.2.0` they can patch out that specific line. What do you think?

Resolving patch:
diff --git a/cirq/contrib/quimb/state_vector.py b/cirq/contrib/quimb/state_vector.py
--- a/cirq/contrib/quimb/state_vector.py
+++ b/cirq/contrib/quimb/state_vector.py
@@ -7,7 +7,21 @@
 
 import cirq
 
-QUIMB_VERSION = tuple(int(x) for x in quimb.__version__.split('.'))
+
+# coverage: ignore
+def _get_quimb_version():
+    """Returns the quimb version and parsed (major,minor) numbers if possible.
+    Returns:
+        a tuple of ((major, minor), version string)
+    """
+    version = quimb.__version__
+    try:
+        return tuple(int(x) for x in version.split('.')), version
+    except:
+        return (0, 0), version
+
+
+QUIMB_VERSION = _get_quimb_version()
 
 
 def circuit_to_tensors(circuit: cirq.Circuit,
@@ -150,9 +164,10 @@ def tensor_expectation_value(circuit: cirq.Circuit,
                    tags={'Q0', 'bra0'}) for q in qubits
     ]
     tn = qtn.TensorNetwork(tensors + end_bras)
-    if QUIMB_VERSION < (1, 3):
+    if QUIMB_VERSION[0] < (1, 3):
         # coverage: ignore
-        warnings.warn('Please use quimb>=1.3 for optimal performance in '
+        warnings.warn(f'quimb version {QUIMB_VERSION[1]} detected. Please use '
+                      f'quimb>=1.3 for optimal performance in '
                       '`tensor_expectation_value`. '
                       'See https://github.com/quantumlib/Cirq/issues/3263')
     else:


Test patch:
Repository: quantumlib/Cirq

Issue:
Read the docs has goofy copyright
**Description of the issue**
Copyright shows up on cirq tutorials on readthedocs.

**How to reproduce the issue**
Go to https://cirq.readthedocs.io/en/latest/docs/gates.html or other pages.  Top part says "Copyright 2020 The Cirq Developers" with apache license.

**Cirq version**
0.9.1.  It probably broke when we adjusted all the copyright notices.



Discussion:
This is the standard header that @lamberta put on every notebook as part of the devsite migration - including the buttons that I strip out during sphinx doc building as they looked even worse. 
It didn't bother me too much because we'll shut down RTD soon, and I'd expect less people to look at the latest link. 

I guess I can strip out the header cell as well fully from RTD publishing. I wonder how ReCirq got around this? @mpharrigan @lamberta? 


The license was a legal requirement for the notebook docs so we need it in the source notebook. But we remove it on the website because we already display the (same) license info in the footer.

For publishing to RTD, stripping it is fine with me as long as it remains in the source.
I did some minor stripping here: https://github.com/quantumlib/ReCirq/pull/64/files#diff-1135f4acf7ec38e9ff5417b385142a20R162 in ReCirq. If you really wanted, you could probably munge out entire cells. I don't think it's a huge issue since we're moving off RTD and the new build system does strip the license info
@mpharrigan yeah, I'm removing the title already in Cirq, inspired by your stripping. I just don't see the ReCirq notebooks having these "@titleLicense" fields on the website (https://recirq.appspot.com/recirq/index.html) is that because you haven't published it since then? 

Resolving patch:
diff --git a/rtd_docs/conf.py b/rtd_docs/conf.py
--- a/rtd_docs/conf.py
+++ b/rtd_docs/conf.py
@@ -132,8 +132,14 @@ def autodoc_process(app, what: str, name: str, obj: Any, options,
 
 
 def source_read(app, docname, source):
-    source[0] = re.sub(r'"##### (Copyright 20\d\d The Cirq Developers)"',
-                       r'"**\1**"', source[0])
+    source[0] = re.sub(r'"##### (Copyright 20\d\d The Cirq Developers)"', r'""',
+                       source[0])
+    source[0] = re.sub(
+        r'(\{\s*?"cell_type": "code".*?"#@title.*License.".*?\},)',
+        r'',
+        source[0],
+        flags=re.S)
+
     source[0] = re.sub(r'"<table.*tfo-notebook-buttons.*"</table>"',
                        r'""',
                        source[0],


Test patch:
Repository: quantumlib/Cirq

Issue:
Docs build is failing
Since the black formatter merge the RTD builds are failing with some weird pip error:

https://readthedocs.org/projects/cirq/builds/

Need to look into it and resolve it if the error is on our end or report it to the RTD team if it's on their end.


Discussion:
Could this be an issue with the new dependency resolver in pip 20.3? It was just released today and changes the default dependency resolver, which has been causing problems in various places.

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -62,7 +62,7 @@
     url='http://github.com/quantumlib/cirq',
     author='The Cirq Developers',
     author_email='cirq@googlegroups.com',
-    python_requires=('>=3.6.0'),
+    python_requires=('>=3.7.0'),
     install_requires=requirements,
     extras_require={
         'contrib': contrib_requirements,


Test patch:
Repository: quantumlib/Cirq

Issue:
q1 == q1 but hash(q1) != hash(q2)
I'm having trouble reproducing this, but I'm in a situation where the thing in the title is happening with `GridQubit`. I've narrowed it down to the fact that the cached `cirq.GridQubit._hash` values are different and recomputing them with `cirq.Qid.__hash__(q1)` gives correct, identical hash functions.

My leading theory is that I'm loading a previously-pickled gridqubit, a copy is being made somewhere and the hash is recomputed. The hash value of `Qid` (the class) is part of the hash input, which could differ over python instantiations 


Discussion:
xref https://github.com/quantumlib/Cirq/pull/3375

relevant: https://docs.python.org/3/library/pickle.html#handling-stateful-objects
We should probably make the hash deterministic, e.g.
```python
self._hash = hash(self.row) ^ hash(self.col)
```

Resolving patch:
diff --git a/cirq/devices/grid_qubit.py b/cirq/devices/grid_qubit.py
--- a/cirq/devices/grid_qubit.py
+++ b/cirq/devices/grid_qubit.py
@@ -281,6 +281,16 @@ def __init__(self, row: int, col: int):
         super().__init__(row, col)
         self._hash = super().__hash__()
 
+    def __getstate__(self):
+        # Don't save hash when pickling; see #3777.
+        state = self.__dict__.copy()
+        del state['_hash']
+        return state
+
+    def __setstate__(self, state):
+        self.__dict__.update(state)
+        self._hash = super().__hash__()
+
     def __hash__(self):
         # Explicitly cached for performance (vs delegating to Qid).
         return self._hash


Test patch:
diff --git a/cirq/devices/grid_qubit_test.py b/cirq/devices/grid_qubit_test.py
--- a/cirq/devices/grid_qubit_test.py
+++ b/cirq/devices/grid_qubit_test.py
@@ -13,9 +13,10 @@
 # limitations under the License.
 """Tests for grid_qubit."""
 
-import pytest
+import pickle
 
 import numpy as np
+import pytest
 
 import cirq
 
@@ -39,6 +40,18 @@ def test_eq():
     eq.make_equality_group(lambda: cirq.GridQid(0, 0, dimension=3))
 
 
+def test_pickled_hash():
+    q = cirq.GridQubit(3, 4)
+    q_bad = cirq.GridQubit(3, 4)
+    q_bad._hash += 1
+    assert q_bad == q
+    assert hash(q_bad) != hash(q)
+    data = pickle.dumps(q_bad)
+    q_ok = pickle.loads(data)
+    assert q_ok == q
+    assert hash(q_ok) == hash(q)
+
+
 def test_str():
     assert str(cirq.GridQubit(5, 2)) == '(5, 2)'
     assert str(cirq.GridQid(5, 2, dimension=3)) == '(5, 2) (d=3)'
Repository: quantumlib/Cirq

Issue:
FrozenCircuit should be able to equal Circuit
In python, freezing an object does not make it unequal. For example:

```
assert frozenset([1, 2]) == set([1, 2])
# passes
```

Currently cirq is breaking this convention:

```
assert cirq.Circuit().freeze() == cirq.Circuit()
# fails
```

Note that this doesn't require the hash codes to be equal. Circuit should still have no hash code, because it is mutable.


Discussion:
Yeah, I pointed this out to @95-martin-orion (https://github.com/quantumlib/Cirq/pull/3445#discussion_r513054808) and then it got lost in the PR shuffles. I agree! 
I wasn't aware of the PYthon convention around this - will have a PR out momentarily.

Resolving patch:
diff --git a/cirq/circuits/circuit.py b/cirq/circuits/circuit.py
--- a/cirq/circuits/circuit.py
+++ b/cirq/circuits/circuit.py
@@ -134,16 +134,16 @@ def __bool__(self):
         return bool(self.moments)
 
     def __eq__(self, other):
-        if not isinstance(other, type(self)):
+        if not isinstance(other, AbstractCircuit):
             return NotImplemented
-        return self.moments == other.moments and self.device == other.device
+        return tuple(self.moments) == tuple(other.moments) and self.device == other.device
 
     def _approx_eq_(self, other: Any, atol: Union[int, float]) -> bool:
         """See `cirq.protocols.SupportsApproximateEquality`."""
-        if not isinstance(other, type(self)):
+        if not isinstance(other, AbstractCircuit):
             return NotImplemented
         return (
-            cirq.protocols.approx_eq(self.moments, other.moments, atol=atol)
+            cirq.protocols.approx_eq(tuple(self.moments), tuple(other.moments), atol=atol)
             and self.device == other.device
         )
 


Test patch:
diff --git a/cirq/circuits/frozen_circuit_test.py b/cirq/circuits/frozen_circuit_test.py
--- a/cirq/circuits/frozen_circuit_test.py
+++ b/cirq/circuits/frozen_circuit_test.py
@@ -26,7 +26,9 @@ def test_freeze_and_unfreeze():
     c = cirq.Circuit(cirq.X(a), cirq.H(b))
 
     f = c.freeze()
-    assert f.moments == tuple(c.moments)
+    # Circuits equal their frozen versions, similar to set(x) == frozenset(x).
+    assert f == c
+    assert cirq.approx_eq(f, c)
 
     # Freezing a FrozenCircuit will return the original.
     ff = f.freeze()
Repository: quantumlib/Cirq

Issue:
Add docstring for `cirq.QasmOutput`
**Is your feature request related to a use case or problem? Please describe.**
The use case is documentation.

**Describe the solution you'd like**
Basically something like the docstring used here: https://github.com/quantumlib/Cirq/blob/d58423a3f06dd0a40fd8acfdd006d9a876274a7c/cirq/circuits/qasm_output.py#L86


**What is the urgency from your perspective for this issue? Is it blocking important work?**

We should do it in the next couple of quarters 
 


Discussion:
I'd like to work on this. If I understand correctly, just the docstring of the `cirq.QasmOutput` constructor is missing, right?
@unaiic That's right. Thanks for picking this up!

Resolving patch:
diff --git a/cirq/circuits/circuit.py b/cirq/circuits/circuit.py
--- a/cirq/circuits/circuit.py
+++ b/cirq/circuits/circuit.py
@@ -2004,8 +2004,8 @@ def insert_at_frontier(
         """Inserts operations inline at frontier.
 
         Args:
-            operations: the operations to insert
-            start: the moment at which to start inserting the operations
+            operations: The operations to insert.
+            start: The moment at which to start inserting the operations.
             frontier: frontier[q] is the earliest moment in which an operation
                 acting on qubit q can be placed.
         """
diff --git a/cirq/circuits/qasm_output.py b/cirq/circuits/qasm_output.py
--- a/cirq/circuits/qasm_output.py
+++ b/cirq/circuits/qasm_output.py
@@ -167,6 +167,18 @@ def __init__(
         precision: int = 10,
         version: str = '2.0',
     ) -> None:
+        """Representation of a circuit in QASM format.
+
+        Args:
+            operations: Tree of operations to insert.
+            qubits: The qubits used in the operations.
+            header: A multi-line string that is placed in a comment at the top
+                of the QASM.
+            precision: The number of digits after the decimal to show for
+                numbers in the QASM code.
+            version: The QASM version to target. Objects may return different
+                QASM depending on version.
+        """
         self.operations = tuple(ops.flatten_to_ops(operations))
         self.qubits = qubits
         self.header = header


Test patch:
Repository: quantumlib/Cirq

Issue:
Change the remaining format strings to `f-string`s
**Description of the issue** 
[Flynt](https://github.com/ikamensh/flynt) was run [here](https://github.com/quantumlib/Cirq/pull/3786) but this required covering some formated lines. This issue is to track that effort.
**How to reproduce the issue**
```
$ pip install flynt
$ flynt .
$ ./check/pytest-and-incremental-coverage 
```
Then cover the remaining lines.

**Cirq version**
The code that is on the master branch.




Discussion:

Resolving patch:
diff --git a/cirq/ops/pauli_string.py b/cirq/ops/pauli_string.py
--- a/cirq/ops/pauli_string.py
+++ b/cirq/ops/pauli_string.py
@@ -959,7 +959,7 @@ def _pass_operation_over(
                     cast(TKey, op.qubits[1]),
                     after_to_before=after_to_before,
                 )
-        raise TypeError('Unsupported operation: {!r}'.format(op))
+        raise NotImplementedError(f'Unsupported operation: {op!r}')
 
     @staticmethod
     def _pass_single_clifford_gate_over(


Test patch:
Repository: quantumlib/Cirq

Issue:
Typos in wait_gate.py::wait
https://github.com/quantumlib/Cirq/blob/150f95c31042669ab9905654998a8432844a4209/cirq/ops/wait_gate.py#L140-L143

They all say picoseconds, but should say picos, nanos, micros, millis.



Discussion:

Resolving patch:
diff --git a/cirq/ops/wait_gate.py b/cirq/ops/wait_gate.py
--- a/cirq/ops/wait_gate.py
+++ b/cirq/ops/wait_gate.py
@@ -138,9 +138,9 @@ def wait(
         *target: The qubits that should wait.
         value: Wait duration (see Duration).
         picos: Picoseconds to wait (see Duration).
-        nanos: Picoseconds to wait (see Duration).
-        micros: Picoseconds to wait (see Duration).
-        millis: Picoseconds to wait (see Duration).
+        nanos: Nanoseconds to wait (see Duration).
+        micros: Microseconds to wait (see Duration).
+        millis: Milliseconds to wait (see Duration).
     """
     return WaitGate(
         duration=value.Duration(


Test patch: