Skip to content

Commit

Permalink
Handle schedules too
Browse files Browse the repository at this point in the history
This commit updates the schedule serialization path too, as it was also
directly loading symengine expressions. The code handling the workaround
is extracted to a standalone function which is used in both spots now
instead of calling symengine directly.
  • Loading branch information
mtreinish committed Oct 1, 2024
1 parent 994be82 commit ea69a45
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 26 deletions.
2 changes: 1 addition & 1 deletion qiskit/qpy/binary_io/schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def _loads_symbolic_expr(expr_bytes, use_symengine=False):
return None
expr_bytes = zlib.decompress(expr_bytes)
if use_symengine:
return load_basic(expr_bytes)
return common.load_symengine_payload(expr_bytes)
else:
from sympy import parse_expr

Expand Down
25 changes: 1 addition & 24 deletions qiskit/qpy/binary_io/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,30 +290,7 @@ def _read_parameter_expression_v3(file_obj, vectors, use_symengine):

payload = file_obj.read(data.expr_size)
if use_symengine:
# This is a horrible hack to workaround the symengine version checking
# it's deserialization does. There were no changes to the serialization
# format between 0.11 and 0.13 but the deserializer checks that it can't
# load across a major or minor version boundary. This works around it
# by just lying about the generating version.
symengine_version = symengine.__version__.split(".")
major = payload[2]
minor = payload[3]
if int(symengine_version[1]) != minor:
if minor not in (11, 13):
raise exceptions.QpyError(
f"Incompatible symengine version {major}.{minor} used to generate the QPY "
"payload"
)
minor_version = int(symengine_version[1])
if minor_version not in (11, 13):
raise exceptions.QpyError(
f"Incompatible installed symengine version {symengine.__version__} to load "
"this QPY payload"
)
payload = bytearray(payload)
payload[3] = minor_version
payload = bytes(payload)
expr_ = load_basic(payload)
expr_ = common.load_symengine_payload(payload)
else:
from sympy.parsing.sympy_parser import parse_expr

Expand Down
35 changes: 34 additions & 1 deletion qiskit/qpy/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@
import io
import struct

from qiskit.qpy import formats
import symengine
from symengine.lib.symengine_wrapper import ( # pylint: disable = no-name-in-module
load_basic,
)

from qiskit.qpy import formats, exceptions

QPY_VERSION = 12
QPY_COMPATIBILITY_VERSION = 10
Expand Down Expand Up @@ -304,3 +309,31 @@ def mapping_from_binary(binary_data, deserializer, **kwargs):
mapping = read_mapping(container, deserializer, **kwargs)

return mapping


def load_symengine_payload(payload: bytes) -> symengine.Expr:
"""Load a symengine expression from it's serialized cereal payload."""
# This is a horrible hack to workaround the symengine version checking
# it's deserialization does. There were no changes to the serialization
# format between 0.11 and 0.13 but the deserializer checks that it can't
# load across a major or minor version boundary. This works around it
# by just lying about the generating version.
symengine_version = symengine.__version__.split(".")
major = payload[2]
minor = payload[3]
if int(symengine_version[1]) != minor:
if minor not in (11, 13):
raise exceptions.QpyError(
f"Incompatible symengine version {major}.{minor} used to generate the QPY "
"payload"
)
minor_version = int(symengine_version[1])
if minor_version not in (11, 13):
raise exceptions.QpyError(
f"Incompatible installed symengine version {symengine.__version__} to load "
"this QPY payload"
)
payload = bytearray(payload)
payload[3] = minor_version
payload = bytes(payload)
return load_basic(payload)

0 comments on commit ea69a45

Please sign in to comment.