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

Add QPY module #250

Merged
Merged

Conversation

rathishcholarajan
Copy link
Member

@rathishcholarajan rathishcholarajan commented Mar 30, 2022

Summary

Copy QPY module from qiskit-terra. (CI works fine with terra main, this should be merged only after qiskit-terra 0.20.0 is released.)

Details and comments

Fixes #147

nkanazawa1989 and others added 2 commits February 24, 2022 02:37
* Move qpy to own module.

qpy_serialization.py is splint into several files for maintenability. This commit also adds several bytes Enum classes for type keys in the header, and provides several helper functions. Some namedtuple class names are updated because, for example, INSTRUCTION will be vague when we add schedule, i.e. it's basically different program and has own instruction that has different data format. Basically CIRCUIT_ prefix is added to them.

* manually cherry-pick #7584 with some cleanup

- change qiskit.qpy.objects -> qiskit.qpy.binary_io
- TUPLE -> SEQUENCE (we may use this for list in future)
- add QpyError
- add _write_register in circuit io to remove boilerplate code

* respond to review comments
- expose several private methods for backward compatibility
- use options for symengine
- rename alphanumeric -> value
- rename write, read methods and remove alias
- improve container read

* remove import warning

* replace alphanumeric with value in comments and messages.

* private functions import

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
…(#7550)

* Add support for custom metadata serializers to QPY load() and dump()

This commit adds a new argument to load(), metadata_serializer, and
dump(), metadata_deserializer, which is used to specify custom
serialization functions to use for serializing the python dictionary for
each circuit's metadata attribute. By default QPY expects the serialized
metadata payload to be encoded as a utf8 json string. But since there
are no user constraints on the metadata dictionary's contents a simple
json.dump() of the circuit's metadata attribute may not be feasible. To
address this issue these new arguments are added to enable users to
specify a custom function to encode the dictionary as binary data
however is required for their circuit's metadata and then read that
custom format as required when deserializing.

The QPY format specification does not change here and still explicitly
lists a UTF8 encoded JSON string as the contents. A fixed format is
needed in the format specification for potential interoperability for
other tools generating QPY data (none exist currently to my knowledge
but nothing precludes it which is why the format is publicly
documented). These new arguments are specific to only the qiskit
implementation and should only be used when generating qpy files and
loading them via qiskit.

* Pivot to use JSONEncoder and JSONDecoder classes for new argument

This commit pivots to leveraging custom JSONEncoder and JSONDecoder
classes for the optional serializer and deserializer arguments instead
of custom callables that return bytes. In the previous commit we used
callables that would be passed the dictionary and returned bytes.
However, while this was flexible it was pretty easy for a user to create
QPY out of spec. While this was documented it is probably easier to just
constrain the argument to always producing valid json. Using custom
encoder and decoder classes let users still handle custom types but also
restrict things to always be JSON. This should fix the potential risk in
the previous iteration but still fix the underlying issue.

* Update release note

* Remove pylint ignores from release note example

Co-authored-by: Jake Lishman <[email protected]>

Co-authored-by: Jake Lishman <[email protected]>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
@rathishcholarajan rathishcholarajan changed the title Add QPY module [Don't merge yet] Add QPY module Mar 30, 2022
qiskit_ibm_runtime/qpy/__init__.py Outdated Show resolved Hide resolved
qiskit_ibm_runtime/qpy/__init__.py Outdated Show resolved Hide resolved
qiskit_ibm_runtime/qpy/__init__.py Outdated Show resolved Hide resolved
Copy link
Collaborator

@daka1510 daka1510 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm personally not a fan of this duplication for two reasons

  1. This comes with an overhead to keep the different implementations in sync. As we've learned with Deprecate auth parameter and add new channel parameter #226, there might be unexpected requirements that force us to change code that we thought can be copied across repositories to save efforts.
  2. Core maintainers of qiskit-ibm-runtime are not familiar with the copied code that now falls into their responsibilities (without dedicated test cases this lack of knowledge introduces a risk to introduce bugs)

Not saying I won't approve but wonder if we have carefully weighed these drawbacks against other options. Wouldn't it make sense to introduce a new python package for core functionality that multiple projects in the qiskit organization depend on?
As far as I understand this should allow us to overcome the timing issue that leads to the problems outlined in #147.

@mtreinish
Copy link
Member

That core package is qiskit-terra. The problem is it moves at a different speed than server side deployment of that core package causing the sync issues.

@mtreinish
Copy link
Member

As for your specific point 2, the solution for that is you don't touch the qpy code here. Just treat it as a vendored dependency and any changes from it have to go through terra first. The point of vendoring it here is to match the qpy version used by the runtime client to something that is known compatible with the server side (which is using a fixed version of terra to deserialize it).

@rathishcholarajan
Copy link
Member Author

I'm personally not a fan of this duplication for two reasons

  1. This comes with an overhead to keep the different implementations in sync. As we've learned with Deprecate auth parameter and add new channel parameter #226, there might be unexpected requirements that force us to change code that we thought can be copied across repositories to save efforts.
  2. Core maintainers of qiskit-ibm-runtime are not familiar with the copied code that now falls into their responsibilities (without dedicated test cases this lack of knowledge introduces a risk to introduce bugs)

Not saying I won't approve but wonder if we have carefully weighed these drawbacks against other options. Wouldn't it make sense to introduce a new python package for core functionality that multiple projects in the qiskit organization depend on? As far as I understand this should allow us to overcome the timing issue that leads to the problems outlined in #147.

The short term problem is the provider is importing private functions from terra now and with terra 0.20 (due today) we won't be able to import a couple of those private functions. If we don't do this users will have serialization issues when using parameterized circuits with Sampler or Estimator. So we need to copy this qpy module from qiskit in order to fix this issue short term. That way we are no longer relying on private functions from terra which I think is an improvement.

The serialization related test cases that we currently have are passing when I run locally. So I believe that is good for now. In the next iteration I will copy over qpy related test cases from terra. I think like Matthew said the key is to not deviate too much in this fork and make any changes only through terra.

@rathishcholarajan
Copy link
Member Author

@mtreinish @daka1510
As for a process to follow for making changes to this, does the following make sense?

  1. Make any changes to qpy module in terra and terra releases the changes.
  2. Copy those qpy module changes to qiskit-ibm-runtime and release qiskit-ibm-runtime.
  3. ntc-provider picks up the latest qiskit-ibm-runtime once it's released. (ntc-provider is not yet using qiskit-ibm-runtime yet).

Please correct me if my understanding is wrong.

@rathishcholarajan rathishcholarajan added the Changelog: New Feature Include in the Added section of the changelog label Mar 31, 2022
@coveralls
Copy link

coveralls commented Mar 31, 2022

Pull Request Test Coverage Report for Build 2072831594

Warning: This coverage report may be inaccurate.

This pull request's base commit is no longer the HEAD commit of its target branch. This means it includes changes from outside the original pull request, including, potentially, unrelated coverage changes.

Details

  • 517 of 831 (62.21%) changed or added relevant lines in 9 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.7%) to 68.671%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit_ibm_runtime/qpy/interface.py 25 27 92.59%
qiskit_ibm_runtime/qpy/exceptions.py 7 10 70.0%
qiskit_ibm_runtime/qpy/common.py 72 110 65.45%
qiskit_ibm_runtime/qpy/binary_io/value.py 107 161 66.46%
qiskit_ibm_runtime/qpy/binary_io/circuits.py 233 450 51.78%
Totals Coverage Status
Change from base Build 2068605667: -0.7%
Covered Lines: 2615
Relevant Lines: 3808

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Changelog: New Feature Include in the Added section of the changelog on hold
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Avoid temporary version inconsistencies between client and server
5 participants