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

Workaround symengine serialization payload incompatibility #13251

Merged
merged 8 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
5 changes: 1 addition & 4 deletions qiskit/qpy/binary_io/schedules.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@

import numpy as np
import symengine as sym
from symengine.lib.symengine_wrapper import ( # pylint: disable = no-name-in-module
load_basic,
)

from qiskit.exceptions import QiskitError
from qiskit.pulse import library, channels, instructions
Expand Down Expand Up @@ -106,7 +103,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
5 changes: 1 addition & 4 deletions qiskit/qpy/binary_io/value.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@

import numpy as np
import symengine
from symengine.lib.symengine_wrapper import ( # pylint: disable = no-name-in-module
load_basic,
)


from qiskit.circuit import CASE_DEFAULT, Clbit, ClassicalRegister
Expand Down Expand Up @@ -290,7 +287,7 @@ def _read_parameter_expression_v3(file_obj, vectors, use_symengine):

payload = file_obj.read(data.expr_size)
if use_symengine:
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)
13 changes: 13 additions & 0 deletions releasenotes/notes/fix-qpy-symengine-compat-858970a9a1d6bc14.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
fixes:
- |
Fixed an issue with :func:`.qpy.load` when loading a QPY payload that
contains a :class:`.ParameterExpression` that was generated when symengine
0.11 was installed and trying to load it in an environment where symengine
0.13 (the latest symengine release as of this qiskit release) or vice versa.
Previously, an error would have been raised by symengine around this version
mismatch. This has been worked around for these two specific symengine versions
but if you're trying to use different versions of symengine and there is a
mismatch with this version of Qiskit this might not work. You will need to
install Qiskit >1.3.0 to fix this mismatch issue more broadly for any potential
future version of symengine.
Loading