-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Add feat(transpiler): add UnrollBoxes pass #15400
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
base: main
Are you sure you want to change the base?
Conversation
|
One or more of the following people are relevant to this code:
|
Pull Request Test Coverage Report for Build 19845452657Details
💛 - Coveralls |
|
Hi Debasmita, thanks for doing this! The code is very clean and mostly LGTM. I had a question though. |
| self.known_annotations = known_annotations or (lambda ann: True) | ||
| self.max_depth = max_depth | ||
|
|
||
| def _validate_annotations(self, box_op: BoxOp, depth: int = 0) -> bool: |
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.
What's the use of the depth argument exactly? I assume that it's to not unroll BoxOps that exceed a certain depth. Will this work fine for the recursive case with multiple nested Boxes? Also I don't see it being passed in the .run(self,dag) function. Is this supposed to be called by the user as well?
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.
Thank @Shobhit21287 . The depth argument was intended for a future extension where UnrollBoxes would stop unrolling once a configurable nesting depth (max_depth) is reached. Right now _validate_annotations is always called without a depth, so the parameter is effectively unused and recursive calls always see depth == 0
|
|
||
| def __init__( | ||
| self, | ||
| recursive: bool = True, |
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.
Hi, thank you for your contribution. I had a couple of clarifications regarding this PR. There is a recursive flag being used over here, and the value is being set. However, I don't see it being reused anywhere else in code. Has it been set for future use? If yes, would you say it makes more sense to keep this addition in a future PR rather than this one?
|
|
||
| for ann_dict in getattr(box_op, "annotations", []): | ||
| if not self.known_annotations(ann_dict): | ||
| return False |
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.
can we add a test case here to test behavior on passing unknown annotations? To ensure that this callable returns False, but the :class:BoxOp remains in the circuit?
| class UnrollBoxes(TransformationPass): | ||
| """Unroll BoxOp operations by replacing them with their internal circuit body.""" | ||
|
|
||
| def __init__( |
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 think there is merit in writing a short doctstring here, defining the input arguments, their types and short descriptions for the :meth:__init__. Since this is a user-facing functionality.
aaryav-3
left a comment
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.
Thank you so much for your contribution, this PR is minimally and effectively written to introduce the new transpilar pass, I just had a couple of doubts and clarifications before it is good to go
Implement a new UnrollBoxes transpiler pass to replace BoxOp “scaffolding” with the gates from the boxed circuit body.
Support nested boxes via @trivial_recurse, so boxes inside boxes are unrolled correctly.
Add an annotation-aware API (known_annotations: Callable[[dict], bool]) so callers can control which annotations are safe to ignore during unrolling.
Fixes Transpiler pass to replace boxes by their contents? #14468