From 4f09f57a365fd6a3ec337f7026d3540a812c2662 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 22:50:51 +0200 Subject: [PATCH] Make `BitArray.{slice_bits,slice_shots,__getitem__}` raise `IndexError` when indices are not valid (backport #12755) (#12844) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Make `BitArray.{slice_bits,slice_shots,__getitem__}` raise `IndexError` when indices are not valid (#12755) * Make BitArray.{slice_bits,slice_shots} raise IndexError when indices are out of bounds * update __getitem__ (cherry picked from commit bfd2eea4807a894fa229cb55b3ad221a50fd31ee) # Conflicts: # qiskit/primitives/containers/bit_array.py * Update bit_array.py --------- Co-authored-by: Takashi Imamichi <31178928+t-imamichi@users.noreply.github.com> Co-authored-by: Elena Peña Tapia <57907331+ElePT@users.noreply.github.com> --- qiskit/primitives/containers/bit_array.py | 21 +++++++++++------- ...ray-slice-bits-shots-c9cb7e5d907722f5.yaml | 11 ++++++++++ .../primitives/containers/test_bit_array.py | 22 +++++++++++++++---- 3 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 releasenotes/notes/fix-bitarray-slice-bits-shots-c9cb7e5d907722f5.yaml diff --git a/qiskit/primitives/containers/bit_array.py b/qiskit/primitives/containers/bit_array.py index f52c852c35fd..5f73339a306d 100644 --- a/qiskit/primitives/containers/bit_array.py +++ b/qiskit/primitives/containers/bit_array.py @@ -131,10 +131,15 @@ def __repr__(self): def __getitem__(self, indices): """Slices the array along an existing axis of the array.""" - if isinstance(indices, tuple) and len(indices) >= self.ndim + 2: - raise ValueError( - "BitArrays cannot be sliced along the bits axis, see slice_bits() instead." - ) + if isinstance(indices, tuple): + if len(indices) == self.ndim + 1: + raise IndexError( + "BitArray cannot be sliced along the shots axis, use slice_shots() instead." + ) + if len(indices) >= self.ndim + 2: + raise IndexError( + "BitArray cannot be sliced along the bits axis, use slice_bits() instead." + ) return BitArray(self._array[indices], self.num_bits) @property @@ -428,13 +433,13 @@ def slice_bits(self, indices: int | Sequence[int]) -> "BitArray": A bit array sliced along the bit axis. Raises: - ValueError: If there are any invalid indices of the bit axis. + IndexError: If there are any invalid indices of the bit axis. """ if isinstance(indices, int): indices = (indices,) for index in indices: if index < 0 or index >= self.num_bits: - raise ValueError( + raise IndexError( f"index {index} is out of bounds for the number of bits {self.num_bits}." ) # This implementation introduces a temporary 8x memory overhead due to bit @@ -455,13 +460,13 @@ def slice_shots(self, indices: int | Sequence[int]) -> "BitArray": A bit array sliced along the shots axis. Raises: - ValueError: If there are any invalid indices of the shots axis. + IndexError: If there are any invalid indices of the shots axis. """ if isinstance(indices, int): indices = (indices,) for index in indices: if index < 0 or index >= self.num_shots: - raise ValueError( + raise IndexError( f"index {index} is out of bounds for the number of shots {self.num_shots}." ) arr = self._array diff --git a/releasenotes/notes/fix-bitarray-slice-bits-shots-c9cb7e5d907722f5.yaml b/releasenotes/notes/fix-bitarray-slice-bits-shots-c9cb7e5d907722f5.yaml new file mode 100644 index 000000000000..56fd81012428 --- /dev/null +++ b/releasenotes/notes/fix-bitarray-slice-bits-shots-c9cb7e5d907722f5.yaml @@ -0,0 +1,11 @@ +--- +upgrade_primitives: + - | + :meth:`.BitArray.slice_bits` and :meth:`.BitArray.slice_shots` + will now raise ``IndexError`` when indices are out of bounds. + They used to raise ``ValueError`` in the case. + - | + :meth:`.BitArray.__getitem__` will now raise ``IndexError`` + when indices are out of bounds or the number of dimensions + of indices does not match that of BitArray. + They used to raise ``ValueError`` in the case. diff --git a/test/python/primitives/containers/test_bit_array.py b/test/python/primitives/containers/test_bit_array.py index 1c8d489b38e4..d4733388d87c 100644 --- a/test/python/primitives/containers/test_bit_array.py +++ b/test/python/primitives/containers/test_bit_array.py @@ -527,6 +527,20 @@ def test_getitem(self): for j in range(2): self.assertEqual(ba.get_counts((0, j, 2)), ba2.get_counts(j)) + with self.subTest("errors"): + with self.assertRaisesRegex(IndexError, "index 2 is out of bounds"): + _ = ba[0, 2, 2] + with self.assertRaisesRegex(IndexError, "index -3 is out of bounds"): + _ = ba[0, -3, 2] + with self.assertRaisesRegex( + IndexError, "BitArray cannot be sliced along the shots axis" + ): + _ = ba[0, 1, 2, 3] + with self.assertRaisesRegex( + IndexError, "BitArray cannot be sliced along the bits axis" + ): + _ = ba[0, 1, 2, 3, 4] + def test_slice_bits(self): """Test the slice_bits method.""" # this creates incrementing bitstrings from 0 to 59 @@ -571,9 +585,9 @@ def test_slice_bits(self): self.assertEqual(ba2.get_counts((i, j, k)), expect) with self.subTest("errors"): - with self.assertRaisesRegex(ValueError, "index -1 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index -1 is out of bounds"): _ = ba.slice_bits(-1) - with self.assertRaisesRegex(ValueError, "index 9 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index 9 is out of bounds"): _ = ba.slice_bits(9) def test_slice_shots(self): @@ -621,9 +635,9 @@ def test_slice_shots(self): self.assertEqual(ba2.get_bitstrings((i, j, k)), expected) with self.subTest("errors"): - with self.assertRaisesRegex(ValueError, "index -1 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index -1 is out of bounds"): _ = ba.slice_shots(-1) - with self.assertRaisesRegex(ValueError, "index 10 is out of bounds"): + with self.assertRaisesRegex(IndexError, "index 10 is out of bounds"): _ = ba.slice_shots(10) def test_expectation_values(self):