-
Notifications
You must be signed in to change notification settings - Fork 205
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
Improve mappers, add ModeBasedMapper #1301
Improve mappers, add ModeBasedMapper #1301
Conversation
Pull Request Test Coverage Report for Build 8719469367Details
💛 - Coveralls |
In looking at the number op timing in your notebook, it looks like #644, in that the timing includes the operator build out. Which is not the case in the parity op one where the operator is built before the call to map() rather than being built as the operator parameter. I do not know how closely things were looked at before. What might be interesting to know is if you put timing in the code around the pauli table buildout how long does that take in comparison to the overall mapping. I imagine that varies a lot though right since the table is built based on the operator width (register size) but the mapping depends on how many terms the operator has. #644 seems to talk about auxiliary operators - if these are normally relatively few terms then the overhead of building the table for each may end up being more significant. And I guess the table being cached should save some memory too. |
Yes, right. Based on the result my suspicion is that building the Pauli table is actually not the most expensive part, but it's a good idea to look at this explicitly. I will try to find some time to do that (but possibly only after Christmas).
That's also a good point. Generally I just took these two examples from the previous issues without much questioning, but I think it would be a good idea to put some thought into coming up with some realistic and meaningful benchmark in some sense. That being said: as I wrote above, I think there is no harm done by doing the caching (on the level of the individual mapper's My guess is that the compose and simplify calls in The main difference regarding the caching is that On a different but related note:I was wondering what the point is of having these two separate methods, Now, My personal sentiment is that I would expect Neither |
Happy New Year everyone! To continue where we left off, I changed the timing of the number operator to not include building the operators. That doesn't change much, however, even for the total time. So building the operators seems to take negligible time compared to the mapper, but caching seems to not have much benefit. For me, the only open question is the "different note" above about whether the |
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.
A few minor details, but overall this LGTM.
Regarding your question about pauli_table
and sparse_pauli_operators
: the separation is likely historical. I don't have a strong opinion on whether this is kept as is or not. However, changing it will require proper deprecation.
Maybe the approach suggested in #1340 could inform a potential new implementation.
@@ -143,7 +143,7 @@ def _logarithmic_encoding( | |||
op.chop() | |||
spin_op_encoding.append(op) | |||
|
|||
return tuple(spin_op_encoding) | |||
return (spin_op_encoding[0], spin_op_encoding[1], spin_op_encoding[2], spin_op_encoding[3]) |
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.
Not sure why this is necessary
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 changed this because otherwise mypy fails due to this issue: python/mypy#7509
- | | ||
The class :class:`.second_q.mappers.ModeBasedMapper` has been added to implement mode based | ||
mapping via a Pauli table (previously part of :class:`.second_q.mappers.QubitMapper`). | ||
upgrade: |
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.
upgrade
is supposed to be things an end user needs to do to upgrade (alter) their code for the release e.g. things have been removed and users code needs to be adjusted. How much is this really just change and part of the features statement - though honestly this is supposed to be more an end user facing statement around the changes where I am not sure how much, if anything, this internal change affects them or surfaces to them in any way. I imagine code they had before using the mappers works just as it did before.
I see Max's comment saying some methods have been removed - that is a case where the user would have to change things so that makes sense, so that would be upgrade, but that just seems to be the last paragraph there
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.
That explanation makes sense. I have removed the point about changes in caching, and the inheritance which I believe has no end user facing consequences. The removal of public methods as pointed out by @mrossinek should obviously stay. Based on your reasoning, the info that pauli_table
is now an instance method instead of a class method should stay, I guess, in case someone is calling it on a class in their 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.
Thanks for your patience and hard work on this! You substantially improved the design of our mappers with this PR 👍
Summary
Adds a new class
ModeBasedMapper
which implements the basic functionality of the mode based mappers (JW, BK, parity, direct mapper) through a Pauli table. Revertspauli_table
to instance method and removes all caching from the parent class. As discussed in #1289.Performance testing
I have performed the tests as in #545 and #644 with code and more plots available here. The results look like this:
Essentially, the effect of caching the Pauli table methods seems marginal. As there appear to be some fringe cases, where caching is somewhat useful (e.g. performances almost doubles for the BK and Parity mappers when mapping large numbers of length 10 number operators but not for length 5 or 15) and no real harm is being done, I implement the caching on the level of the individual
pauli_table
implementations. For this, the instance methodpauli_table
simply calls the private static method_pauli_table
which is cached. This way, one can keep the caching for the existing mappers, but can also implement new mappers that actually use thatpauli_table
is an instance method.