Skip to content
This repository was archived by the owner on Jul 28, 2023. It is now read-only.

Serialize numpy arrays with object types #1119

Merged
merged 2 commits into from
Feb 21, 2022
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
4 changes: 4 additions & 0 deletions qiskit/providers/ibmq/runtime/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ def default(self, obj: Any) -> Any: # pylint: disable=arguments-differ
if isinstance(obj, complex):
return {'__type__': 'complex', '__value__': [obj.real, obj.imag]}
if isinstance(obj, np.ndarray):
if obj.dtype == object:
return {"__type__": "ndarray", "__value__": obj.tolist()}
value = _serialize_and_encode(obj, np.save, allow_pickle=False)
return {'__type__': 'ndarray', '__value__': value}
if isinstance(obj, set):
Expand Down Expand Up @@ -255,6 +257,8 @@ def object_hook(self, obj: Any) -> Any:
if obj_type == 'complex':
return obj_val[0] + 1j * obj_val[1]
if obj_type == 'ndarray':
if isinstance(obj_val, list):
return np.array(obj_val)
return _decode_and_deserialize(obj_val, np.load)
if obj_type == 'set':
return set(obj_val)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
fixes:
- |
Fixed an issue where numpy ndarrays with object types could not be
serialized. :class:`qiskit.providers.ibmq.runtime.RuntimeEncoder` and
:class:`qiskit.providers.ibmq.runtime.RuntimeDecoder` have been updated
to handle these ndarrays.
13 changes: 13 additions & 0 deletions test/ibmq/runtime/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,19 @@ def test_encoder_datetime(self):
decoded = json.loads(encoded, cls=RuntimeDecoder)
self.assertEqual(decoded, obj)

def test_encoder_ndarray(self):
"""Test encoding and decoding a numpy ndarray."""
subtests = (
{"ndarray": np.array([[1, 2, 3], [{"obj": 123}, 5, 6]], dtype=object)},
{"ndarray": np.array([[1, 2, 3], [{"obj": 123}, 5, 6]])},
{"ndarray": np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=int)},
)
for obj in subtests:
encoded = json.dumps(obj, cls=RuntimeEncoder)
self.assertIsInstance(encoded, str)
decoded = json.loads(encoded, cls=RuntimeDecoder)
self.assertTrue(np.array_equal(decoded["ndarray"], obj["ndarray"]))

def test_encoder_instruction(self):
"""Test encoding and decoding instructions"""
subtests = (
Expand Down