Skip to content

Conversation

ikkoham
Copy link
Contributor

@ikkoham ikkoham commented May 10, 2022

Summary

Allow decorators enhance Primitives (Sampler and Estimator) and provide a more flexible interface.
This PR comes from the discussion: #7723 (comment).

Details and comments

  • Built Docs

image

image

@ikkoham ikkoham added Changelog: New Feature Include in the "Added" section of the changelog mod: primitives Related to the Primitives module labels May 10, 2022
@qiskit-bot
Copy link
Collaborator

Thank you for opening a new pull request.

Before your PR can be merged it will first need to pass continuous integration tests and be reviewed. Sometimes the review process can be slow, so please be patient.

While you're waiting, please feel free to review other open PRs. While only a subset of people are authorized to approve pull requests for merging, everyone is encouraged to review open pull requests. Doing reviews helps reduce the burden on the core team and helps make the project's code better for everyone.

One or more of the the following people are requested to review this:

@coveralls
Copy link

coveralls commented May 10, 2022

Pull Request Test Coverage Report for Build 2300436201

  • 127 of 156 (81.41%) changed or added relevant lines in 3 files are covered.
  • 3 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.01%) to 84.351%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qiskit/primitives/decorators/allow.py 124 153 81.05%
Files with Coverage Reduction New Missed Lines %
qiskit/pulse/library/waveform.py 3 89.36%
Totals Coverage Status
Change from base Build 2291551136: -0.01%
Covered Lines: 54599
Relevant Lines: 64728

💛 - Coveralls

@Cryoris
Copy link
Contributor

Cryoris commented May 10, 2022

With this PR, would users have to define a new primitive class to enable e.g. passing circuits as objects? Because that seems like some overhead that's not necessarily obvious...

@blakejohnson
Copy link
Contributor

I would like to rename circuit_indices and observable_indices to just circuits and observables as well.

Why are you going with a decorator approach here? Why not just allow objects to be passed as part of the fundamental interface?

Copy link
Collaborator

@HuangJunye HuangJunye left a comment

Choose a reason for hiding this comment

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

Overall I agree with the points raised by @Cryoris and @blakejohnson. I find the decorator syntax and the need of defining a new class very confusing. Can we add these as flags or just directly allow all of these options in the standard interface?

Comment on lines +79 to +90
with CustomEstimator([ansatz], [observable]) as e:
result = e(
circuit_indices=[ansatz],
observable_indices=[observable],
parameter_values=[parameter],
)
print(result)

Object equivalency is determined by the object ID. Thus, note that even if they represent the same
circuit (e.g. ``copy()``), they will not match if they are different objects.
Also, note that since qiskit's circuit objects and observable objects are not immutable,
if the object is changed after the construction of the primitives, it may behave unexpectedly.
Copy link
Collaborator

@HuangJunye HuangJunye May 11, 2022

Choose a reason for hiding this comment

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

What happens when the object inside the "context" doesn't match with those in the with ... as ...? Since we are passing objects, would it be possible to make it so that we only pass objects inside the "context" like:

with CustomEstimator() as e: # no need to pass anything
    result = e(
        circuit_indices=[ansatz],
        observable_indices=[observable],
        parameter_values=[parameter],
    )

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This extension is not impossible if a circuit update feature is included, but the communication and serialization overhead would be significant.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I don't quite understand the what you said, probably because I don't understand the whole python context concept. Do you know some resources to understand the context manager better? I am going to read PEP343 where this was introduced.

Do you know any major software that uses the context manager? I would like to see more code examples. The only thing I know is for openning files.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is not a context issue, but simply because the cost of circuit serialization and communication is high, so it is faster to communicate a small object like int.

(Major software: for example, requests has Session() that can be used with with.)

@ikkoham
Copy link
Contributor Author

ikkoham commented May 12, 2022

Thanks. There is an O(len(circuits)) overhead to find the corresponding object. This is inevitable.

decorator syntax

I essentially only came up with this method.
It is true that decorators may be difficult. However, this is possible.

with allow_objects(Estimator)([ansatz], [observable]):
    result = e(
        circuit_indices=[ansatz],
        observable_indieces=[observable],
        parameter_values=[parameter],
    )

It is difficult to modify internal of the estimator class since it is costly for all Runtime services and 3rd parties’ primitives to implement this.

naming of circuit_indices

In the first implementation this argument was named circuits.
But, circuit_indices is suggested by @levbishop. #7818

@ikkoham
Copy link
Contributor Author

ikkoham commented May 12, 2022

It just occurred to me that it is indeed possible to implement this on the base class side. If so, the discussion
is whether we want the default behavior or a custom one. I went with custom because I believe that these
interfaces need to be used carefully by users who fully understand them, but it is possible to make them
default. Which would you prefer?

@HuangJunye
Copy link
Collaborator

I personally think that these 3 decorators should be the default behaviour but I can see that the decorator approach is very flexible and easily extendable. Is there other decorators for primitives you have in mind?

And Is it possible to use more than one decorator at a time?

@ikkoham
Copy link
Contributor Author

ikkoham commented May 13, 2022

After discussing this issue offline with @levbishop and @ajavadia, we decided to make it default instead of custom decorator and migrate the argument names.

@HuangJunye

Is there other decorators for primitives you have in mind?

Not at the moment, but gradients could be implemented with mixin or decorator. (but now that direction is not a good idea).

And Is it possible to use more than one decorator at a time?

Yes, it's possible. But I think in this PR the decorators are orthogonal, but in some cases the order may affect.

@ikkoham ikkoham mentioned this pull request May 16, 2022
1 task
@ikkoham ikkoham closed this May 17, 2022
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 mod: primitives Related to the Primitives module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants