Repository: quantumlib/Cirq (Python)

Issue:
cirq.measure_pauli_string rejects negated pauli strings
```
import cirq
cirq.measure_single_paulistring(-cirq.Y(cirq.LineQubit(0))*cirq.Y(cirq.LineQubit(1)), key='1')
```


Discussion:
This should be fairly straightforward to fix.  We raise an error if the pauli string is does not have a coefficient of 1 here - https://github.com/quantumlib/Cirq/blob/9a1609ce8800ed1aa82bbf6261f5f7b8a41b81cf/cirq-core/cirq/ops/measure_util.py#L55

However, the underlying `PauliMeasurementGate` does support `DensePauliString`s with coefficient +1 and -1. So, instead of passing `pauli_observable.values()` to construct the `PauliMeasurementGate`, we can just pass `pauli_observable.dense(pauli_observable.keys())` and then remove the check for coefficient being exactly +1. 

https://github.com/quantumlib/Cirq/blob/9a1609ce8800ed1aa82bbf6261f5f7b8a41b81cf/cirq-core/cirq/ops/measure_util.py#L60
I can take this issue.



Patch:
diff --git a/cirq-core/cirq/ops/measure_util.py b/cirq-core/cirq/ops/measure_util.py
index 49cf84a812f..600e5bebc93 100644
--- a/cirq-core/cirq/ops/measure_util.py
+++ b/cirq-core/cirq/ops/measure_util.py
@@ -46,18 +46,22 @@ def measure_single_paulistring(
 
     Raises:
         ValueError: if the observable is not an instance of PauliString or if the coefficient
-            is not +1.
+            is not +1 or -1.
     """
     if not isinstance(pauli_observable, pauli_string.PauliString):
         raise ValueError(
             f'Pauli observable {pauli_observable} should be an instance of cirq.PauliString.'
         )
-    if pauli_observable.coefficient != 1:
-        raise ValueError(f"Pauli observable {pauli_observable} must have a coefficient of +1.")
+    if abs(pauli_observable.coefficient) != 1:
+        raise ValueError(
+            f"Pauli observable {pauli_observable} must have a coefficient of +1 or -1."
+        )
 
     if key is None:
         key = _default_measurement_key(pauli_observable)
-    return PauliMeasurementGate(pauli_observable.values(), key).on(*pauli_observable.keys())
+    return PauliMeasurementGate(pauli_observable.dense(list(pauli_observable.keys())), key).on(
+        *pauli_observable.keys()
+    )
 
 
 def measure_paulistring_terms(


Test patch:
diff --git a/cirq-core/cirq/ops/measure_util_test.py b/cirq-core/cirq/ops/measure_util_test.py
index 8967c1ac736..b7ac8d7fab5 100644
--- a/cirq-core/cirq/ops/measure_util_test.py
+++ b/cirq-core/cirq/ops/measure_util_test.py
@@ -95,6 +95,12 @@ def test_measure_single_paulistring():
         ps.values(), key='a'
     ).on(*ps.keys())
 
+    # Test with negative coefficient
+    ps_neg = -cirq.Y(cirq.LineQubit(0)) * cirq.Y(cirq.LineQubit(1))
+    assert cirq.measure_single_paulistring(ps_neg, key='1').gate == cirq.PauliMeasurementGate(
+        cirq.DensePauliString('YY', coefficient=-1), key='1'
+    )
+
     # Empty application
     with pytest.raises(ValueError, match='should be an instance of cirq.PauliString'):
         _ = cirq.measure_single_paulistring(cirq.I(q[0]) * cirq.I(q[1]))
@@ -103,9 +109,9 @@ def test_measure_single_paulistring():
     with pytest.raises(ValueError, match='should be an instance of cirq.PauliString'):
         _ = cirq.measure_single_paulistring(q)
 
-    # Coefficient != +1
+    # Coefficient != +1 or -1
     with pytest.raises(ValueError, match='must have a coefficient'):
-        _ = cirq.measure_single_paulistring(-ps)
+        _ = cirq.measure_single_paulistring(-2 * ps)
 
 
 def test_measure_paulistring_terms():