-
Notifications
You must be signed in to change notification settings - Fork 586
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 operator transform functionality #2240
Conversation
Hello. You may have forgotten to update the changelog!
|
Codecov Report
@@ Coverage Diff @@
## master #2240 +/- ##
==========================================
+ Coverage 96.60% 99.28% +2.67%
==========================================
Files 232 233 +1
Lines 18713 18808 +95
==========================================
+ Hits 18078 18673 +595
+ Misses 635 135 -500
Continue to review full report at Codecov.
|
raise OperationTransformError( | ||
f"Wires in circuit {tape.wires.tolist()} are inconsistent with " | ||
f"those in wire_order {wire_order.tolist()}" | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check may be expensive, but probably not wise to just ignore, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I copied this from get_unitary_matrix
, what do you think? Worth removing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really don't know...maybe leave for now, and sacrifice for speed later!
- Supports datastructures that may contain multiple operations, such as | ||
a tape, QNode, or qfunc. | ||
|
||
- Supports being used with a functional transform UI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the explanation in the PR description, and find it more useful that this one. I wonder if there is an easier way to tell a developer if she needs this transform, and what it does? Maybe with a few in-line examples already up here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! I'd think even just saying that we'd like to allow func(qml.RY)(0.3, wires=0)
and not just func(qml.RY(0.3, wires=0))
(which comes "out-of-the-box" with a standard Python function) could be helpful.
The reader could then contemplate what the real diff between the two is and read on for more explanation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an amazing feature to have! 😍 🎆 It will be so useful.
I've left comments. The functionality seems to work well and is very nicely tested! The logic is a bit challenging to follow at times and the UI itself could still do with some thinking. Could it maybe be broken down into two separate steps? (op_transform + registration)
Using ``op_transform`` is not necessary in most cases; simply define a | ||
standard Python function that accepts an operator and returns the | ||
computed quantity. | ||
|
||
However, this registration class is useful if you wish to easily create | ||
a function that: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: reading this, how about changing the order?
- The cases when
op_transform
is useful are presented; - There's a note that all the other cases can be done via a standard Python function.
I think, when reading, one is most interested in what the feature could be used for, maybe good to have it first?
- Supports datastructures that may contain multiple operations, such as | ||
a tape, QNode, or qfunc. | ||
|
||
- Supports being used with a functional transform UI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed! I'd think even just saying that we'd like to allow func(qml.RY)(0.3, wires=0)
and not just func(qml.RY(0.3, wires=0))
(which comes "out-of-the-box" with a standard Python function) could be helpful.
The reader could then contemplate what the real diff between the two is and read on for more explanation.
Co-authored-by: antalszava <antalszava@gmail.com>
Co-authored-by: antalszava <antalszava@gmail.com>
r"""Convert a function that applies to operators into a functional transform. | ||
|
||
This allows the operator function to be used across PennyLane | ||
on both instantiated operators as well as quantum functions. | ||
|
||
By default, this decorator creates functional transforms that | ||
accept a single operator. However, you can also register how the | ||
transform acts on multiple operators. Once this is defined, | ||
the transform can be used anywhere in PennyLane --- at the operator | ||
level for operator arithmetic, or at the qfunc/QNode level. | ||
|
||
.. warning:: | ||
|
||
This is an experimental feature, and is subject to change. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mariaschuld @antalszava I've completely re-written the docstring summary from scratch, let me know if this is better!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me 💯
Co-authored-by: antalszava <antalszava@gmail.com>
Context:
Currently, it is complex and unwieldy to write new functions that apply to operators in PennyLane, for several reasons:
We aim to support multiple UIs, including applying the function directly to an instantiated operator,
as well as a functional approach
The function must know how to deal with both a single
Operator
object, as well as multiple operators in the form of a tapeThe function must be usable both as a decorator and inline
The function could support optional parameters that determine its usage
operator functions sometimes need to take into account wire ordering
All of this results in a big barrier to contributions, while also requiring that contributors know about the internal implementation details of a lot of PennyLane's core.
In addition, for functions of operators that have already been implemented (e.g.,
get_unitary_matrix()
,adjoint()
,ctrl()
), the same code boilerplate that enables the above UI is often repeated, not sufficiently tested, and error prone.Description of the Change:
Abstracts away all of the boilerplate required to construct the above UI into a single, well tested and well documented decorator
@qml.op_transform
.Decorating a function of an operator with
qml.op_transform
enables it to be used as per the context section, with minimal overhead to the developer.Wire ordering is taken into account automatically, and depends on the object the transform is applied to. For tapes and qfuncs, the wires available on the tape define the wire ordering. For QNodes, the wires available on the device define the wire ordering.
By default, it creates transforms that accept a single operator. However, you can also register how the transform acts on a tape of multiple operators. Once this is defined, the transform can be used anywhere in PennyLane --- at the operator level for operator arithmetic, or at the qfunc/qnode level.
There is no restriction to what the transform returns; it can return another operator, or an arbitrary object such as a matrix or a string. E.g.,
draw()
,trace()
,matrix()
etc. can all be rewritten using this framework.Operator transforms that return operators are special -- they are also qfunc transforms, since the output of the operator transform will always be quantum in nature. As a result, they can be used within PennyLane's compilation frameworks.
Benefits: Will standardize a UI pattern that has been long assumed, ensure it is well tested, and make it a lot easier for contributors to contribute functions that act on operators.
Possible Drawbacks:
The name
Possible confusion with the other transform decorators.
Once this PR is merged, I plan to revisit the transform decorators, and see if they can be unified under a single
@qml.transform
decorator that smartly knows which decorator to use under the hood.Related GitHub Issues: n/a