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

Improve finding an auxiliary wire the hadamard gradient #6872

Open
albi3ro opened this issue Jan 21, 2025 · 0 comments
Open

Improve finding an auxiliary wire the hadamard gradient #6872

albi3ro opened this issue Jan 21, 2025 · 0 comments

Comments

@albi3ro
Copy link
Contributor

albi3ro commented Jan 21, 2025

This issue is reserved for internal use.

Problem:

The hadamard_grad gradient transform requires an auxiliary wire. It can determine this auxiliary via manual gradient keyword arguments aux_wire and device_wires. If neither of these are found, it just uses the next largest integer.

For example, the device wires can be manually provided:

dev = qml.device('default.qubit', wires=("a", "b"))

@qml.qnode(dev, diff_method="hadamard", device_wires=dev.wires)
def circuit(x):
    qml.RX(x, "a")
    return qml.expval(qml.Z("a"))

jax.grad(circuit)(0.5)
Array(-0.47942554, dtype=float64)

If the device wires are not provided in such a situation, we will get an error, even when an extra wire exists.

dev = qml.device('default.qubit', wires=("a", "b"))

@qml.qnode(dev, diff_method="hadamard")
def circuit(x):
    qml.RX(x, "a")
    return qml.expval(qml.Z("a"))

jax.grad(circuit)(0.5)
WireError: Cannot run circuit(s) on default.qubit as they contain wires not found on the device: {0}

This error provides no information about where wire 0 came from. It wasn't present in the original circuit, but added by the hadamard gradient transform.

The solution:

To improve our handling of auxiliary wires, we want to add logic to our workflow setup to automatically add the device_wires if they weren't present in the user-gradient keyword args.

We already have similar logic for adding the device to the gradient_keyword_arguments for qml.gradients.param_shift_cv:

if execution_config.gradient_method is qml.gradients.param_shift_cv:

We can add a similar line to the same spot for the qml.gradients.hadamard_grad gradient method.

If dev_wires or aux_wires are already in the gradient keyword arguments, we do not need to add the device wires.

Once we've made the above change we should be able to execute the following without error:

dev = qml.device('default.qubit', wires=("a", "b"))

@qml.qnode(dev, diff_method="hadamard")
def circuit(x):
    qml.RX(x, "a")
    return qml.expval(qml.Z("a"))

jax.grad(circuit)(0.5)

When running

dev = qml.device('default.qubit', wires=1)

@qml.qnode(dev, diff_method="hadamard")
def circuit(x):
    qml.RX(x, 0)
    return qml.expval(qml.Z(0))

jax.grad(circuit)(0.5)

The user should get:

WireError: The device has no free wire for the auxiliary wire.

instead of the current:

WireError: Cannot run circuit(s) on default.qubit as they contain wires not found on the device: {1}

Solution Requirements:

Unit tests should be added to test_resolve_execution_config.py checking that:

  • The device wires are added to the gradient keyword arguments if they aren't already there
  • The device wires are not added to the gradient keyword arguments if device_wires or aux_wire are already specified

For a similar test, see:

def test_param_shift_cv_kwargs():

Integration tests should be added to tests/gradients/core/test_hadamard_gradient.py

The PR should include a changelog entry, and follow black and pylint standards.

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

No branches or pull requests

1 participant