Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix BitArray.from_counts/from_samples to not fail for input with only 0 outcome and num_bits=None (backport #12800) #12821

Merged
merged 1 commit into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions qiskit/primitives/containers/bit_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,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
Expand Down Expand Up @@ -275,7 +275,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.
Expand All @@ -298,6 +298,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)
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
14 changes: 14 additions & 0 deletions test/python/primitives/containers/test_bit_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,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)
Expand All @@ -238,6 +239,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"])
Expand All @@ -246,6 +251,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"])
Expand All @@ -254,6 +262,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])
Expand All @@ -262,6 +273,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
Expand Down
Loading