diff --git a/qiskit/primitives/containers/bit_array.py b/qiskit/primitives/containers/bit_array.py index 5c68893a4da2..11cd91a96521 100644 --- a/qiskit/primitives/containers/bit_array.py +++ b/qiskit/primitives/containers/bit_array.py @@ -233,7 +233,7 @@ def from_counts( Args: counts: One or more counts-like mappings with the same number of shots. num_bits: The desired number of bits per shot. If unset, the biggest value found sets - this value. + this value, with a minimum of one bit. Returns: A new bit array with shape ``()`` for single input counts, or ``(N,)`` for an iterable @@ -277,7 +277,7 @@ def from_samples( Args: samples: A list of bitstrings, a list of integers, or a list of hexstrings. num_bits: The desired number of bits per sample. If unset, the biggest sample provided - is used to determine this value. + is used to determine this value, with a minimum of one bit. Returns: A new bit array. @@ -300,6 +300,9 @@ def from_samples( # we are forced to prematurely look at every iterand in this case ints = list(ints) num_bits = max(map(int.bit_length, ints)) + # convention: if the only value is 0, represent with one bit: + if num_bits == 0: + num_bits = 1 num_bytes = _min_num_bytes(num_bits) data = b"".join(val.to_bytes(num_bytes, "big") for val in ints) diff --git a/releasenotes/notes/fix-bitarray-fromcounts-nobits-82958a596b3489ec.yaml b/releasenotes/notes/fix-bitarray-fromcounts-nobits-82958a596b3489ec.yaml new file mode 100644 index 000000000000..6be5ea21bdf5 --- /dev/null +++ b/releasenotes/notes/fix-bitarray-fromcounts-nobits-82958a596b3489ec.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - | + Fixed a bug in :meth:`.BitArray.from_counts` and :meth:`.BitArray.from_samples`. + Previously these would raise an error if given data containing only zeros, and no + value for the optional argument ``num_bits``. Now they produce a :class:`.BitArray` + with :attr:`.BitArray.num_bits` set to 1. diff --git a/test/python/primitives/containers/test_bit_array.py b/test/python/primitives/containers/test_bit_array.py index e4963d046f51..4aeeba854b33 100644 --- a/test/python/primitives/containers/test_bit_array.py +++ b/test/python/primitives/containers/test_bit_array.py @@ -232,6 +232,7 @@ def convert(counts: Counts): counts1 = convert(Counts({"0b101010": 2, "0b1": 3, "0x010203": 4})) counts2 = convert(Counts({1: 3, 2: 6})) + counts3 = convert(Counts({0: 2})) bit_array = BitArray.from_counts(counts1) expected = BitArray(u_8([[0, 0, 42]] * 2 + [[0, 0, 1]] * 3 + [[1, 2, 3]] * 4), 17) @@ -248,6 +249,10 @@ def convert(counts: Counts): ] self.assertEqual(bit_array, BitArray(u_8(expected), 17)) + bit_array = BitArray.from_counts(counts3) + expected = BitArray(u_8([[0], [0]]), 1) + self.assertEqual(bit_array, expected) + def test_from_samples_bitstring(self): """Test the from_samples static constructor.""" bit_array = BitArray.from_samples(["110", "1", "1111111111"]) @@ -256,6 +261,9 @@ def test_from_samples_bitstring(self): bit_array = BitArray.from_samples(["110", "1", "1111111111"], 20) self.assertEqual(bit_array, BitArray(u_8([[0, 0, 6], [0, 0, 1], [0, 3, 255]]), 20)) + bit_array = BitArray.from_samples(["000", "0"]) + self.assertEqual(bit_array, BitArray(u_8([[0], [0]]), 1)) + def test_from_samples_hex(self): """Test the from_samples static constructor.""" bit_array = BitArray.from_samples(["0x01", "0x0a12", "0x0105"]) @@ -264,6 +272,9 @@ def test_from_samples_hex(self): bit_array = BitArray.from_samples(["0x01", "0x0a12", "0x0105"], 20) self.assertEqual(bit_array, BitArray(u_8([[0, 0, 1], [0, 10, 18], [0, 1, 5]]), 20)) + bit_array = BitArray.from_samples(["0x0", "0x0"]) + self.assertEqual(bit_array, BitArray(u_8([[0], [0]]), 1)) + def test_from_samples_int(self): """Test the from_samples static constructor.""" bit_array = BitArray.from_samples([1, 2578, 261]) @@ -272,6 +283,9 @@ def test_from_samples_int(self): bit_array = BitArray.from_samples([1, 2578, 261], 20) self.assertEqual(bit_array, BitArray(u_8([[0, 0, 1], [0, 10, 18], [0, 1, 5]]), 20)) + bit_array = BitArray.from_samples([0, 0, 0]) + self.assertEqual(bit_array, BitArray(u_8([[0], [0], [0]]), 1)) + def test_reshape(self): """Test the reshape method.""" # this creates incrementing bitstrings from 0 to 360 * 32 - 1