-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Support merging 1-qubit gates in transformers for parameterized circuits #7149
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
3dea74b
to
d5da63a
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #7149 +/- ##
========================================
Coverage 98.66% 98.67%
========================================
Files 1106 1110 +4
Lines 96086 96266 +180
========================================
+ Hits 94808 94987 +179
- Misses 1278 1279 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Hi Eliott, Nour, I have added the function to support one use case. Could you PTAL? For the use case of combined input of sweep and parameterized circuit, will be added in the followup PR. Let's first make sure this PR is in the right place and do the right job. Thanks! |
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 tested it a little bit in this colab, and it doesn't seem to work properly yet, the interface looks good to me.
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.
One small comment: it would be nice if the merged single-qubit gates ended up in the same moment; see this cell of the colab. |
Got you, thanks a lot for the manual checks! I will update the pr accordingly and fix checks. |
33a8233
to
7ac61a5
Compare
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.
there are several useful private methods that should be turned into public transformers
|
||
|
||
def _values_of_sweep(sweep: Sweep, key: str | sympy.Symbol): | ||
p = sympy.Symbol(key) if isinstance(key, str) else key |
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'm not sure about this
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.
Removed this util func.
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.
It's from
Cirq/cirq-core/cirq/study/sweeps_test.py
Line 249 in 5112418
def _values(sweep, key): |
resolved_circuits: A list of circuits where symbols have been replaced with concrete values. | ||
symbolized_single_tag: The tag applied to single-qubit operations that originally | ||
contained symbols before parameterizations. | ||
|
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.
some parameters are missing
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.
obsolete.
|
||
def _merge_single_qubit_gates_to_phxz_symbolized( | ||
resolved_circuits: List['cirq.AbstractCircuit'], | ||
symbolized_single_tag: str, |
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.
tags are not necessarily strings
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.
Done. all tags type -> Hashable.
return [resolver.value_of(p) for resolver in sweep] | ||
|
||
|
||
def _merge_single_qubit_gates_to_phxz_symbolized( |
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 this method is useful on its own ... so it should be public
maybe even turn it into a class an split its logic across 2+ methods
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.
Done.
return the_merge_tag.pop().split("_")[-1] | ||
|
||
|
||
def _map_merged_ops_to_symbolized_phxz( |
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 should be a public transformer method
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.
Done in symbolize.py .
Note: if users expect update sweeps together with merging, it's not supported yet. It's a todo item to be supported in the followup PRs.
tag_transformers: remove_tags, index_tags. symbolize: symbolize_single_qubit_gates_by_indexed_tags
Thanks Nour for the valuable suggestions. I come up with a much better version with your inputs. @NoureldinYosri I added Could you help take another look? (I can split the tag_transformer, symbolize transformers out in different prs if this PR is too huge). |
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.
lets split this PR into smaller PRs ... also what is happening with all these tags?
@@ -65,6 +76,7 @@ def merge_single_qubit_gates_to_phxz( | |||
circuit: 'cirq.AbstractCircuit', | |||
*, | |||
context: Optional['cirq.TransformerContext'] = None, | |||
merge_tags_fn: Optional[Callable[['cirq.CircuitOperation'], List[Hashable]]] = None, |
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 feel like this is a bit too general ... what is the problem with recieving a list of tags ?
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 kind of need a function here as what I need to do is given a circuit op, set the output tags with more rule based tag setters and I believe the flexibility of the function can help users in different use cases.
- Currently, the merge function do the following mapping in the
rewriter
CircuitOperation(X['tag_needed'] -- Y['tag1']) --> phxz(x,z,a) with no tags
- In my use case, I need a rule based tag setter:
case 1: CircuitOperation(X['tag_needed'] -- Y['tag1']) --'tag_needed' presented--> phxz(...)['phxz_{iter}']
case 2: CircuitOperation(X -- Z) --no 'tags_needed' found --> phxz(...) with no tags
- Flexibility of merge_tags_fn: e.g., if users want to preserve all the tags in the circuit op, they may do the merges in merge_tags_fn, then the tags can preserve like the following
CircuitOperation(X['tag0'] -- Y['tag1']) --> phxz(...)['tag0', 'tag1']
) | ||
merged_circuits.append(merged_circuit) | ||
|
||
if not all( |
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 don't think this should happen here ... this should be a test for the correctness of the transformer
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.
It's to validate the input parameters sweep
, basically all the resolvers in sweep shoulld resolve the circuit to the same structure, otherwise, we can't do the merge here.
If we don't check here, Step 2 of parameterization would possibly crash with different kind of errors.
I should probably update the error message as InvalidArgument("Invalid input
sweep, different resolvers in sweep resulted in different merged structures.")
Thanks! @NoureldinYosri I will split the PRs =) |
Input: symbolized_circuit, sweep
Output: new_symbolzied_circuit, new_sweep