Skip to content
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

HT gradient - additional modes #7046

Open
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

dtlics
Copy link

@dtlics dtlics commented Mar 5, 2025

Context: Hadamard gradients method variants

Description of the Change: added support for different modes in hadamard gradient and implemented direct HT, reversed HT and reversed_direct HT

Benefits: more variants of HT + measurement grouping generates better efficiency for gradient estimation

Possible Drawbacks: for reversed methods, that is reversed HT and reversed_direct HT, the current version does not support circuits with multiple measurements. One will need to modify the processing_fn in how it aggregates the results so support this. For non-reversed methods, we aggregate for each measurement and the code work because the shape is N_G*M where N_G is the number of terms in the generator and M is the number of measurements. However, in reversed method, the shape is [N_1, ..., N_M], where for the i-th measurement, there are N_i gradient tapes. Different measurement has different number of tapes, and all the tape has only one measurement, so one does not need to aggregate across dimensions, just group neighboring ones would do.

Related GitHub Issues:

dtlics added 3 commits March 4, 2025 23:05
…and finished reversed method for single measurement

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
@dtlics dtlics requested review from albi3ro and isaacdevlugt March 5, 2025 04:51
@dtlics dtlics self-assigned this Mar 5, 2025
@albi3ro
Copy link
Contributor

albi3ro commented Mar 5, 2025

So for the failing test, we keep a hardcoded list of potential gradient keyword arguments here:

SUPPORTED_GRADIENT_KWARGS = {

This was done as a patch to add validation to the QNode(qfunc, dev, ... , **gradient_kwargs) way of passing gradient keyword arguments and catching mistakes. Gladly, we will be getting rid of that in April, but for now, we will need to add "mode" to that hardcoded set.

Comment on lines 388 to 399
# Get a generator and coefficients
sub_coeffs, generators = _get_pauli_generators(trainable_op)

# Create measurement with gate generators
# With type pennylane.measurements.expval.ExpectationMP
mp = qml.expval(
qml.Hamiltonian(
coeffs=sub_coeffs,
observables=generators,
# grouping_type="commuting",
)
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we are using the generator as a meausrement, do we still need to represent the observable as a linear combination of unitaries (paulis)?

Or could we technically just do:

mp = qml.expval(trainable_op.generator() @ qml.Y(aux_wire))

This might be a bit more general, and leaves interpreting the new observable up to the device.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, I changed the how the measurements are constructed, everything works well so far.

I also added the keyword "mode" into that hardcoded set.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, with this implementation, if a user wants to minimize the number of distinct circuits, would the device be able to apply measurement grouping with respect to this expval?

Copy link
Contributor

@albi3ro albi3ro Mar 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. Measuremet grouping is on by default now with split_non_commuting.

dtlics added 3 commits March 11, 2025 14:57

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
Copy link

codecov bot commented Mar 11, 2025

Codecov Report

Attention: Patch coverage is 23.61111% with 55 lines in your changes missing coverage. Please review.

Project coverage is 99.48%. Comparing base (897c041) to head (036e3fc).
Report is 14 commits behind head on master.

Files with missing lines Patch % Lines
pennylane/gradients/hadamard_gradient.py 23.61% 55 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #7046      +/-   ##
==========================================
- Coverage   99.60%   99.48%   -0.12%     
==========================================
  Files         490      496       +6     
  Lines       47256    47393     +137     
==========================================
+ Hits        47070    47151      +81     
- Misses        186      242      +56     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

return new_batch, new_coeffs

def _reversed_hadamard_test(tape, trainable_param_idx, aux_wire) -> tuple[list, list]:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reversed and direct reversed, can we add a check making sure there is only one meausrement, and raising a ValueError if not?

We could also add this validation up near the other validation checks, like the assert_no_state.

The benefit of having it here is that we've already dispatched by mode, but the benefit of having it by the other assertions is that we would only have to run it once.

all supported quantum operation arguments. More info is in the documentation
for :func:`qml.gradients.hadamard_grad <.gradients.hadamard_grad>`.

* ``"reversed-hadamard"``: A variant of ``"hadamard"``, where the role of the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point, the different modes are accessible via:

qml.QNode(f, dev, diff_method="hadamard", gradient_kwargs={"mode": "reversed"})

To automatically choose the mode from a string diff_method, we will need to update this workflow function:

def _resolve_diff_method(

to be able to interpret the various hadamard options. We can do so in this PR, but I'd prefer to do that in a follow on.

Copy link
Contributor

@albi3ro albi3ro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given direct and reversed direct don't need an aux wire, bypass the the extraction of the aux_wire if the mode is direct or revesed direct:

    aux_wire = _get_aux_wire(aux_wire, tape, device_wires)

Potentially just leaving it None if when we don't need it. This will allow us to direct and reversed direct when we don't have any bonus wires.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants