diff --git a/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py b/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py index 34e524348bf8..50b80ec89051 100644 --- a/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +++ b/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py @@ -167,7 +167,16 @@ def __init__( # move the phase of `pauli_list` to `self._coeffs` phase = pauli_list._phase count_y = pauli_list._count_y() - self._coeffs = np.asarray((-1j) ** (phase - count_y) * coeffs, dtype=coeffs.dtype) + + # Compute exponentiation via integer arithmetic and lookup table to avoid + # floating point errors + exponent = (phase - count_y) % 4 + lookup = np.array([1 + 0j, -1j, -1 + 0j, 1j], dtype=coeffs.dtype) + + vals = lookup[exponent] + self._coeffs = vals * coeffs + + # Update pauli_list phase pauli_list._phase = np.mod(count_y, 4) self._pauli_list = pauli_list diff --git a/releasenotes/notes/sparse-pauli-op-heavy-weight-fix-aa822428643d642a.yaml b/releasenotes/notes/sparse-pauli-op-heavy-weight-fix-aa822428643d642a.yaml new file mode 100644 index 000000000000..d285c6fb6857 --- /dev/null +++ b/releasenotes/notes/sparse-pauli-op-heavy-weight-fix-aa822428643d642a.yaml @@ -0,0 +1,7 @@ +fixes: + - | + Fixed a bug where a initializing :class:`.SparsePauliOp` with a large + number of Pauli-``Y`` terms (typically :math:`\geq 100`) and no explicit + ``coeffs`` would result in a coefficient close to 1 but with a floating point + error. The coefficient is now correctly 1 per default. + Fixed `#13522 `__. \ No newline at end of file diff --git a/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py b/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py index 766011042e43..3602492030c4 100644 --- a/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py +++ b/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py @@ -140,6 +140,11 @@ def test_sparse_pauli_op_init(self): coeffs[:] = 0 self.assertEqual(spp_op, ref_op) + def test_sparse_pauli_op_init_long_ys(self): + """Test heavy-weight SparsePauliOp initialization.""" + y = SparsePauliOp("Y" * 1000) + self.assertEqual(1, y.coeffs[0]) + @ddt.ddt class TestSparsePauliOpConversions(QiskitTestCase):