From 94c3ab37f338590ba5115cc005313ee0fb5ad340 Mon Sep 17 00:00:00 2001 From: Max Rossmannek Date: Fri, 9 Sep 2022 15:00:50 +0200 Subject: [PATCH] feat: support sum(LinearMixin) (#8722) * feat: support sum(LinearMixin) This enables the use of `sum(...)` for subclasses of the `LinearMixin` class. It also adds the reflective operand dunder methods `__radd__` and `__rsub__`. * Add crossreferences to release note Co-authored-by: Jake Lishman --- .../quantum_info/operators/mixins/linear.py | 16 ++++++++++ .../base-operators-sums-d331e78a9fa4b5d8.yaml | 5 +++ .../quantum_info/operators/test_scalar_op.py | 32 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 releasenotes/notes/base-operators-sums-d331e78a9fa4b5d8.yaml diff --git a/qiskit/quantum_info/operators/mixins/linear.py b/qiskit/quantum_info/operators/mixins/linear.py index a512df475a45..2167848e1552 100644 --- a/qiskit/quantum_info/operators/mixins/linear.py +++ b/qiskit/quantum_info/operators/mixins/linear.py @@ -38,6 +38,18 @@ class LinearMixin(MultiplyMixin, ABC): """ def __add__(self, other): + # enable easy use of sum(...) + if not isinstance(other, type(self)) and other == 0: + return self + + qargs = getattr(other, "qargs", None) + return self._add(other, qargs=qargs) + + def __radd__(self, other): + # enable easy use of sum(...) + if not isinstance(other, type(self)) and other == 0: + return self + qargs = getattr(other, "qargs", None) return self._add(other, qargs=qargs) @@ -45,6 +57,10 @@ def __sub__(self, other): qargs = getattr(other, "qargs", None) return self._add(-other, qargs=qargs) + def __rsub__(self, other): + qargs = getattr(other, "qargs", None) + return (-self)._add(other, qargs=qargs) + @abstractmethod def _add(self, other, qargs=None): """Return the CLASS self + other. diff --git a/releasenotes/notes/base-operators-sums-d331e78a9fa4b5d8.yaml b/releasenotes/notes/base-operators-sums-d331e78a9fa4b5d8.yaml new file mode 100644 index 000000000000..1c92d6d6e85c --- /dev/null +++ b/releasenotes/notes/base-operators-sums-d331e78a9fa4b5d8.yaml @@ -0,0 +1,5 @@ +--- +features: + - | + ``qiskit.quantum_info.BaseOperator`` subclasses (like :class:`.ScalarOp`, + :class:`.SparsePauliOp` and :class:`.PauliList`) can now be used with ``sum``. diff --git a/test/python/quantum_info/operators/test_scalar_op.py b/test/python/quantum_info/operators/test_scalar_op.py index 45079f8d0cc6..3f5b11ef56f3 100644 --- a/test/python/quantum_info/operators/test_scalar_op.py +++ b/test/python/quantum_info/operators/test_scalar_op.py @@ -168,6 +168,27 @@ def test_add(self, coeff1, coeff2): target = coeff1 + coeff2 self.assertScalarOp(val, dims, target) + @combine(coeff1=[0, 1, -3.1, 1 + 3j]) + def test_radd(self, coeff1): + """Test right-side addition with ScalarOp.""" + dims = (3, 2) + op1 = ScalarOp(dims, coeff=coeff1) + + val = op1 + 0 + self.assertScalarOp(val, dims, coeff1) + + @combine(coeff1=[0, 1, -3.1, 1 + 3j], coeff2=[-1, -5.1 - 2j]) + def test_sum(self, coeff1, coeff2): + """Test add operation with ScalarOp. ({coeff1} + {coeff2})""" + # Add two ScalarOps + dims = (3, 2) + op1 = ScalarOp(dims, coeff=coeff1) + op2 = ScalarOp(6, coeff=coeff2) + + val = sum([op1, op2]) + target = coeff1 + coeff2 + self.assertScalarOp(val, dims, target) + @combine(coeff1=[0, 1, -3.1, 1 + 3j], coeff2=[-1, -5.1 - 2j]) def test_subtract(self, coeff1, coeff2): """Test add operation with ScalarOp. ({coeff1} - {coeff2})""" @@ -179,6 +200,17 @@ def test_subtract(self, coeff1, coeff2): target = coeff1 - coeff2 self.assertScalarOp(val, dims, target) + @combine(coeff1=[0, 1, -3.1, 1 + 3j], coeff2=[-1, -5.1 - 2j]) + def test_rsub(self, coeff1, coeff2): + """Test right-side subtraction with ScalarOp.""" + dims = (3, 2) + op1 = ScalarOp(dims, coeff=coeff1) + op2 = ScalarOp(dims, coeff=coeff2) + + val = op2.__rsub__(op1) + target = coeff1 - coeff2 + self.assertScalarOp(val, dims, target) + @combine( coeff1=[0, 1, -3.1, 1 + 3j], coeff2=[-1, -5.1 - 2j],