Skip to content

Commit 136aaff

Browse files
authored
Fix SparsePauliOp initialization with dense Y labels (Qiskit#13580)
* used modular arithmetic to fix floating point error in heavy-weight sparse_pauli_op * fix comments * reformatted * added release notes and addressed comments * addressed comments * formatted * addressed comments * addressed comments * addressed all comments * formatted
1 parent eced049 commit 136aaff

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,16 @@ def __init__(
167167
# move the phase of `pauli_list` to `self._coeffs`
168168
phase = pauli_list._phase
169169
count_y = pauli_list._count_y()
170-
self._coeffs = np.asarray((-1j) ** (phase - count_y) * coeffs, dtype=coeffs.dtype)
170+
171+
# Compute exponentiation via integer arithmetic and lookup table to avoid
172+
# floating point errors
173+
exponent = (phase - count_y) % 4
174+
lookup = np.array([1 + 0j, -1j, -1 + 0j, 1j], dtype=coeffs.dtype)
175+
176+
vals = lookup[exponent]
177+
self._coeffs = vals * coeffs
178+
179+
# Update pauli_list phase
171180
pauli_list._phase = np.mod(count_y, 4)
172181
self._pauli_list = pauli_list
173182

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fixes:
2+
- |
3+
Fixed a bug where a initializing :class:`.SparsePauliOp` with a large
4+
number of Pauli-``Y`` terms (typically :math:`\geq 100`) and no explicit
5+
``coeffs`` would result in a coefficient close to 1 but with a floating point
6+
error. The coefficient is now correctly 1 per default.
7+
Fixed `#13522 <https://github.com/Qiskit/qiskit/issues/13522>`__.

test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ def test_sparse_pauli_op_init(self):
140140
coeffs[:] = 0
141141
self.assertEqual(spp_op, ref_op)
142142

143+
def test_sparse_pauli_op_init_long_ys(self):
144+
"""Test heavy-weight SparsePauliOp initialization."""
145+
y = SparsePauliOp("Y" * 1000)
146+
self.assertEqual(1, y.coeffs[0])
147+
143148

144149
@ddt.ddt
145150
class TestSparsePauliOpConversions(QiskitTestCase):

0 commit comments

Comments
 (0)