-
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 qml.generator(op)
function
#2256
Conversation
Co-authored-by: Maria Schuld <mariaschuld@gmail.com>
…to matrix-function
Hello. You may have forgotten to update the changelog!
|
qml.generator(op)
functionqml.generator(op)
function
Codecov Report
@@ Coverage Diff @@
## master #2256 +/- ##
==========================================
+ Coverage 99.28% 99.31% +0.02%
==========================================
Files 236 237 +1
Lines 18869 18899 +30
==========================================
+ Hits 18734 18769 +35
+ Misses 135 130 -5
Continue to review full report at Codecov.
|
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.
Nice addition @josh146 ! :)
Once the minor comments are addressed I'm happy to approve.
Do you plan to include the changes that allow multi-version compatibility which we discussed earlier in this PR or a new one?
@@ -63,8 +63,7 @@ def get_spectrum(op, decimals): | |||
Returns: | |||
set[float]: non-negative frequencies contributed by this input-encoding gate | |||
""" | |||
matrix, coeff = get_generator(op, return_matrix=True) | |||
matrix = coeff * matrix | |||
matrix = qml.matrix(qml.generator(op, format="observable")) |
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 could have been done in #2182 already, but now that we're touching this code, we could simply use parameter_frequencies
instead of this whole utility function? Might be a separate PR, though (maybe together with Rotosolve using parameter_frequencies
, grouping it into an "application" PR).
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.
good idea!
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.
@dwierichs which would you prefer, doing it here, or doing it in a separate PR?
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 guess a separate one that uses parameter_frequencies
where applicable is more clean? :)
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.
yep :)
op = qml.Rot(0.1, 0.2, 0.3, wires=0) | ||
|
||
class CustomOp(qml.operation.Operation): | ||
num_wires = 1 | ||
num_params = 1 | ||
|
||
op = CustomOp(0.5, wires=0) |
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.
Out of curiousity: Why was this change required? :)
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.
@cvjjm suggested (very wisely) to move the num_params
validation before getting the generator. So this test started raising 'Generator only supports single param operations' instead!
I couldn't think of another gate that would fit the test, and probably better practise to have test data designed for the test.
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 the explanation :)
Co-authored-by: David Wierichs <davidwierichs@gmail.com>
Co-authored-by: Maria Schuld <mariaschuld@gmail.com>
with warnings.catch_warnings(): | ||
warnings.filterwarnings( | ||
action="ignore", message=r".+ eigenvalues will be computed numerically\." | ||
) | ||
eigvals = qml.eigvals(qml.generator(self, format="observable")) | ||
|
||
if isinstance(gen, qml.SparseHamiltonian): | ||
mat = gen.sparse_matrix().toarray() | ||
eigvals = tuple(np.round(np.linalg.eigvalsh(mat), 8)) | ||
return qml.gradients.eigvals_to_frequencies(eigvals) | ||
eigvals = tuple(np.round(eigvals, 8)) | ||
return qml.gradients.eigvals_to_frequencies(eigvals) |
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.
@dwierichs I made the change here because I realized the old version was simply duplicating qml.eigvals()
; this makes the method cleaner, and less likely to break in the future.
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.
Oh great, this does look very nice :)
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! :)
Context:
Currently, to get the generator of an operator, you must do
op.generator()
.However, there are many downsides to this:
op.generator()
is overwritten by each operator, and thus does not take into account behaviour like operator inversesOperators can return arbitrary operators as generators. Until this is standardized, we need to consider Hamiltonians and matrices separately!
If the generator is a Pauli word, it is sometimes nice to be able to extract the 'prefactor'.
Currently,
qml.utils.get_generator()
is available which is a temporary function to address the above.Description of the Change:
Adds
qml.generator()
, which generalizes the temporaryqml.utils.get_generator()
Remove
qml.utils.get_generator()
.Generalize
qml.generator()
to return generators in various different formats:"prefactor"
, as per the old system"observable"
, as per the operator defines"hamiltonian"
, always return a Hamiltonian.Benefits: As above.
Possible Drawbacks: Not a drawback per se, but this function will become a lot simpler once the operator subclasses are merged.
Related GitHub Issues: n/a