From 1054fba42c3c36007d5af4335480601135591396 Mon Sep 17 00:00:00 2001 From: daxfo Date: Wed, 15 Oct 2025 18:48:36 -0700 Subject: [PATCH 1/4] Ensure GateOperation.add does not interfere with Circuit.radd --- cirq-core/cirq/circuits/circuit_test.py | 23 +++++++++--------- cirq-core/cirq/ops/gate_operation.py | 4 ++++ cirq-core/cirq/ops/linear_combinations.py | 4 ++++ .../cirq/ops/linear_combinations_test.py | 24 +++++++++++++++++++ 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/cirq-core/cirq/circuits/circuit_test.py b/cirq-core/cirq/circuits/circuit_test.py index cd8f7b00c70..6b3eb0fdb55 100644 --- a/cirq-core/cirq/circuits/circuit_test.py +++ b/cirq-core/cirq/circuits/circuit_test.py @@ -356,20 +356,21 @@ def test_add_op_tree(circuit_cls) -> None: @pytest.mark.parametrize('circuit_cls', [cirq.Circuit, cirq.FrozenCircuit]) -def test_radd_op_tree(circuit_cls) -> None: +@pytest.mark.parametrize('gate', [cirq.X, cirq.H]) +def test_radd_op_tree(circuit_cls, gate) -> None: a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') c = circuit_cls() - assert [cirq.X(a), cirq.Y(b)] + c == circuit_cls([cirq.Moment([cirq.X(a), cirq.Y(b)])]) + assert [gate(a), cirq.Y(b)] + c == circuit_cls([cirq.Moment([gate(a), cirq.Y(b)])]) - assert cirq.X(a) + c == circuit_cls(cirq.X(a)) - assert [cirq.X(a)] + c == circuit_cls(cirq.X(a)) - assert [[[cirq.X(a)], []]] + c == circuit_cls(cirq.X(a)) - assert (cirq.X(a),) + c == circuit_cls(cirq.X(a)) - assert (cirq.X(a) for _ in range(1)) + c == circuit_cls(cirq.X(a)) + assert gate(a) + c == circuit_cls(gate(a)) + assert [gate(a)] + c == circuit_cls(gate(a)) + assert [[[gate(a)], []]] + c == circuit_cls(gate(a)) + assert (gate(a),) + c == circuit_cls(gate(a)) + assert (gate(a) for _ in range(1)) + c == circuit_cls(gate(a)) with pytest.raises(AttributeError): - _ = cirq.X + c + _ = gate + c with pytest.raises(TypeError): _ = 0 + c @@ -380,9 +381,9 @@ def test_radd_op_tree(circuit_cls) -> None: else: d = cirq.Circuit() d.append(cirq.Y(b)) - assert [cirq.X(a)] + d == circuit_cls([cirq.Moment([cirq.X(a)]), cirq.Moment([cirq.Y(b)])]) - assert cirq.Moment([cirq.X(a)]) + d == circuit_cls( - [cirq.Moment([cirq.X(a)]), cirq.Moment([cirq.Y(b)])] + assert [gate(a)] + d == circuit_cls([cirq.Moment([gate(a)]), cirq.Moment([cirq.Y(b)])]) + assert cirq.Moment([gate(a)]) + d == circuit_cls( + [cirq.Moment([gate(a)]), cirq.Moment([cirq.Y(b)])] ) diff --git a/cirq-core/cirq/ops/gate_operation.py b/cirq-core/cirq/ops/gate_operation.py index f565b13d2c8..b8cc8e97f08 100644 --- a/cirq-core/cirq/ops/gate_operation.py +++ b/cirq-core/cirq/ops/gate_operation.py @@ -332,12 +332,16 @@ def __rmul__(self, other: Any) -> Any: return self.gate._rmul_with_qubits(self._qubits, other) def __add__(self, other): + if not isinstance(other, (ops.Operation, int)): + return NotImplemented return 1 * self + other def __radd__(self, other): return other + 1 * self def __sub__(self, other): + if not isinstance(other, (ops.Operation, int)): + return NotImplemented return 1 * self - other def __rsub__(self, other): diff --git a/cirq-core/cirq/ops/linear_combinations.py b/cirq-core/cirq/ops/linear_combinations.py index 3dfcaff536b..69049095095 100644 --- a/cirq-core/cirq/ops/linear_combinations.py +++ b/cirq-core/cirq/ops/linear_combinations.py @@ -742,6 +742,8 @@ def __len__(self) -> int: return len(self._linear_dict) def __iadd__(self, other): + if isinstance(other, raw_types.Operation): + other = pauli_string._try_interpret_as_pauli_string(other) if isinstance(other, numbers.Complex): other = PauliSum.from_pauli_strings([PauliString(coefficient=other)]) elif isinstance(other, PauliString): @@ -766,6 +768,8 @@ def __rsub__(self, other): return -self.__sub__(other) def __isub__(self, other): + if isinstance(other, raw_types.Operation): + other = pauli_string._try_interpret_as_pauli_string(other) if isinstance(other, numbers.Complex): other = PauliSum.from_pauli_strings([PauliString(coefficient=other)]) elif isinstance(other, PauliString): diff --git a/cirq-core/cirq/ops/linear_combinations_test.py b/cirq-core/cirq/ops/linear_combinations_test.py index d95e6d35447..b50ea4ea0e8 100644 --- a/cirq-core/cirq/ops/linear_combinations_test.py +++ b/cirq-core/cirq/ops/linear_combinations_test.py @@ -975,10 +975,18 @@ def test_paulisum_validation() -> None: ps += cirq.I(cirq.LineQubit(0)) assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)})) + ps = cirq.PauliSum() + ps = cirq.I(cirq.LineQubit(0)) + ps + assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)})) + ps = cirq.PauliSum() ps -= cirq.I(cirq.LineQubit(0)) assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(-1)})) + ps = cirq.PauliSum() + ps = cirq.I(cirq.LineQubit(0)) - ps + assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)})) + def test_add_number_paulisum() -> None: q = cirq.LineQubit.range(2) @@ -1008,6 +1016,22 @@ def test_add_number_paulistring() -> None: == cirq.PauliSum.from_pauli_strings([cirq.PauliString() * 2, cirq.PauliString({a: cirq.X})]) ) + assert ( + cirq.X(a) - 2 + == -2 + cirq.X(a) + == cirq.PauliSum.from_pauli_strings( + [cirq.PauliString() * -2, cirq.PauliString({a: cirq.X})] + ) + ) + + assert ( + 2 - cirq.X(a) + == 2 + -cirq.X(a) + == cirq.PauliSum.from_pauli_strings( + [cirq.PauliString() * 2, -cirq.PauliString({a: cirq.X})] + ) + ) + def test_pauli_sum_formatting() -> None: q = cirq.LineQubit.range(2) From 7c45553ce224a4b054701d3de0ad125cdf7ce8fa Mon Sep 17 00:00:00 2001 From: daxfo Date: Wed, 15 Oct 2025 19:26:49 -0700 Subject: [PATCH 2/4] change int check to number check --- cirq-core/cirq/ops/gate_operation.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/gate_operation.py b/cirq-core/cirq/ops/gate_operation.py index b8cc8e97f08..a035500f2a7 100644 --- a/cirq-core/cirq/ops/gate_operation.py +++ b/cirq-core/cirq/ops/gate_operation.py @@ -16,6 +16,7 @@ from __future__ import annotations +import numbers import re import warnings from types import NotImplementedType @@ -332,7 +333,7 @@ def __rmul__(self, other: Any) -> Any: return self.gate._rmul_with_qubits(self._qubits, other) def __add__(self, other): - if not isinstance(other, (ops.Operation, int)): + if not isinstance(other, (ops.Operation, numbers.Number)): return NotImplemented return 1 * self + other @@ -340,7 +341,7 @@ def __radd__(self, other): return other + 1 * self def __sub__(self, other): - if not isinstance(other, (ops.Operation, int)): + if not isinstance(other, (ops.Operation, numbers.Number)): return NotImplemented return 1 * self - other From 0fe4fb3ce75712261ea96f90926d17420a4b9c2b Mon Sep 17 00:00:00 2001 From: Dax Fohl Date: Wed, 12 Nov 2025 21:18:34 -0800 Subject: [PATCH 3/4] Update cirq-core/cirq/ops/linear_combinations_test.py Co-authored-by: Pavol Juhas --- cirq-core/cirq/ops/linear_combinations_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/linear_combinations_test.py b/cirq-core/cirq/ops/linear_combinations_test.py index b50ea4ea0e8..6155786ee66 100644 --- a/cirq-core/cirq/ops/linear_combinations_test.py +++ b/cirq-core/cirq/ops/linear_combinations_test.py @@ -975,8 +975,7 @@ def test_paulisum_validation() -> None: ps += cirq.I(cirq.LineQubit(0)) assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)})) - ps = cirq.PauliSum() - ps = cirq.I(cirq.LineQubit(0)) + ps + ps = cirq.I(cirq.LineQubit(0)) + cirq.PauliSum() assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)})) ps = cirq.PauliSum() From 9bbf44f75b4b70cc91da85069bbb6fc3d95ea88c Mon Sep 17 00:00:00 2001 From: Dax Fohl Date: Wed, 12 Nov 2025 21:18:42 -0800 Subject: [PATCH 4/4] Update cirq-core/cirq/ops/linear_combinations_test.py Co-authored-by: Pavol Juhas --- cirq-core/cirq/ops/linear_combinations_test.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cirq-core/cirq/ops/linear_combinations_test.py b/cirq-core/cirq/ops/linear_combinations_test.py index 6155786ee66..c27f55e8c3f 100644 --- a/cirq-core/cirq/ops/linear_combinations_test.py +++ b/cirq-core/cirq/ops/linear_combinations_test.py @@ -982,8 +982,7 @@ def test_paulisum_validation() -> None: ps -= cirq.I(cirq.LineQubit(0)) assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(-1)})) - ps = cirq.PauliSum() - ps = cirq.I(cirq.LineQubit(0)) - ps + ps = cirq.I(cirq.LineQubit(0)) - cirq.PauliSum() assert ps == cirq.PauliSum(cirq.LinearDict({frozenset(): complex(1)}))