-
Notifications
You must be signed in to change notification settings - Fork 50
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
QREF integration #1194
QREF integration #1194
Conversation
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Awesome! This will be great to have in the repository! Thanks so much for opening a PR. I suspect we may have a couple nits before merging, but this looks like a great start. We'll have to add qref to the dependencies. For better or for worse, we've been putting our interop dependencies alongside the ordinary runtime dependencies (maybe we'll factor these out into optional dependencies in the future) in |
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.
Thanks for opening the PR! The conversion already looks great!
I've left a round of comments and suggestions.
A dictionary that can be unpacked into arguments of RoutineV1 initializer. | ||
""" | ||
ports = [port for reg in bloq.signature for port in _ports_from_register(reg)] | ||
local_variables = {} |
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 you add a comment explaining what's the use case for local_variables
? It seems like it may be used when the string representation of the symbolic size of a qualtran register does not satisfy the isIdentifier()
condition which is needed for any string to be a valid port size in QREF ?
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.
After some thoughts I decided this logic should actually go to bartiq
, will update bartiq
and then remove it from 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.
Actually, it would require some major changes in bartiq and if done like this it should work, so I'll leave it as it is.
Added 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.
An extra question – is there a way to get all the symbols used in a particular bloq
?
In most cases the symbols taken from signature
are enough, but sometimes (e.g. in PermutationCycle
), I don't know how to retrieve the information that it requires having L
defined, other than parsing the t_complexity
of it.
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.
We don't have an interface that does exactly this. We often try to treat symbols and concrete values as similarly as possible in the code (this was our design decision; it has its plus-es and minus-es). In practice, this means symbols get passed in as constructor arguments (aka bloq attributes). But they can be arbitrarily hidden:
N, L = sympy.symbols("N L", positive=True, integer=True)
cycle = Shaped((L,))
permutation_cycle_symb = PermutationCycle(N, cycle)
the L
symbol is passed as a constructor argument, but contained within a Shaped
object (which we use to support cases where the concrete value is an array but we only need the shape to do e.g. resource counts).
Since everything is an attrs
dataclass, you can extract the bloq attributes with (pseudocode)
fields = attrs.fields(bloq)
vals = {f.name: getattrs(bloq, f.name) for f in fields}
so you can see that the vals dictionary contains {'N': sympy.Symbol('N')
(easy), and 'cycle': Shaped(sympy.Symbol('L'))}
(you have to poke at it to see that it has a symbol named L
def bloq_to_routine(obj, name: Optional[str] = None): | ||
"""Import object from Qualtran by converting it into corresponding QREF RoutineV1 object. | ||
|
||
Args: | ||
obj: object to be imported. Can be either Bloq or BloqInstance. | ||
name: optional name override. This can be useful e.g. if you are converting | ||
CompositeBloq (which do not store meaningful names in Qualtran) and | ||
know some good name for it. | ||
|
||
Return: | ||
A Bartiq object corresponding to the source Qualtran object. For both Bloqs | ||
and BloqInstances the returned object is of type RoutineV1. | ||
|
||
""" |
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.
If I understand correctly, as part of the conversion; we are not doing any bloq decompositions and the expectation is that the user should flatten out a bloq that has a decomposition into a CompositeBloq
at an appropriate level and then convert the CompositeBloq
to qref's SchemaV1
; the conversion would not have any further information about the structure of the subbloqs (eg: info about decomposing a bloq that appears in the composite bloq but is not decomposed). Is this understanding correct?
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.
Yes, that's correct.
If there is a preferred way to perform the decomposition down to arbitrary level, we could add an option to perform it while doing the conversion. However, I felt this would be an overkill for the first iteration and it's better to be explicit with what's being converted for now.
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.
sounds good, I think this is fine as long as we're clear that a RoutineV1
is analogous to one CompositeBloq
"/Users/mstechly/Documents/code/2024-06-26-qualtran-conversion/bartiq/src/bartiq/compilation/_compile.py:117: UserWarning: Found the following issues with the provided routine after the compilation has finished: [\"Input param N found in subroutine: CompositeBloq.PrepareUniformSuperposition_0, which is not among top level params: {'PrepareUniformSuperposition_0.N'}.\"]\n", | ||
" warnings.warn(\n" |
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.
We usually clear the output of all notebooks before committing them. The notebooks are run before generating the docs so that the docs generated on https://qualtran.readthedocs.io/en/latest/index.html have the expected output.
Can you please clear all output from the notebook (assuming the notebooks runs after qualtran runtime dependencies are updated)
@@ -0,0 +1,311 @@ | |||
import networkx as nx |
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.
nit: I think it's worth splitting up this file into smaller files with methods grouped based on the function they are performing. But happy to merge it as a single file for now and leave the reorganization as a future improvement.
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'd prefer to leave it for reorganization in future.
Also, I think it's worth adding |
@tanujkhattar I'll do as you suggested with the separate PR for the dependencies once this PR is clean and I make any necessary changes in qref/bartiq (there's at least one right now). |
@@ -0,0 +1,261 @@ | |||
from dev_tools.qualtran_dev_tools.bloq_finder import get_bloq_examples |
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.
@mpharrigan This is not part of the qualtran package; so we should probably not use it in tests to avoid adding a dependency.
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.
Yeah, @mstechly called it out in the original PR description. For the tests, I'd recommend picking a few key examples to test the qref interop functionality and then later we can add
- a qref conversion check to the "bloq report card" which is run ad-hoc
- a qref conversion check to the
bloq_autotester
pytest fixture, which will run against most bloq examples
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.
Ok, I've chosen some examples (open to using other examples) and changed the code.
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 I have addressed all the feedback, let me know what you think.
@@ -0,0 +1,261 @@ | |||
from dev_tools.qualtran_dev_tools.bloq_finder import get_bloq_examples |
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.
Ok, I've chosen some examples (open to using other examples) and changed the code.
@tanujkhattar @mpharrigan – I've signed the CLA and ran all the checks locally to make sure they're passing. Apart from the outstanding discussion, some other comments:
Hopefully we can close it soon 😅 |
This is fine, especially from a test file; and because this is a bloq example, so it's not "private" in the traditional sense. I'll merge the version bump PR, take a final look over this, and we should be able to merge imminently! |
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 great! Really nice notebook
I added
qref_interop
module to Qualtran.There's a couple of issues with this PR:
qref_interop
, but it's actually not "interop" but "one-way conversion" at this moment. Should we rename it or leave it as is?get_bloq_examples
fromdev_tools
. However, this is outside from Qualtran package, so not a way to go. I like the functionality though, so perhaps it's worth moving it to the Qualtran package?CC @mpharrigan @tanujkhattar