Skip to content

Commit

Permalink
Fix SparsePauliOp initialization with dense Y labels (#13580) (
Browse files Browse the repository at this point in the history
…#13611)

* 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

(cherry picked from commit 136aaff)

Co-authored-by: trigpolynom <[email protected]>
  • Loading branch information
mergify[bot] and trigpolynom authored Jan 6, 2025
1 parent d83565c commit 768bd04
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 1 deletion.
11 changes: 10 additions & 1 deletion qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,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

Expand Down
Original file line number Diff line number Diff line change
@@ -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 <https://github.com/Qiskit/qiskit/issues/13522>`__.
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down

0 comments on commit 768bd04

Please sign in to comment.