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

One-shot for noise in Python #26

Merged
merged 4 commits into from
Oct 30, 2024
Merged

Conversation

WrathfulSpatula
Copy link
Collaborator

PennyLane development teams says in PennyLaneAI/pennylane#6463 (comment) that implementing one-shot mode is the back end developers' responsibility. This is a problem, because, if it's our responsibility in Catalyst, too, it becomes very complicated to save the circuit to run for every single shot. We basically need to completely redundantly implement our own equivalent of a circuit "tape."

However, this fix handles it on the Python side. I'm on the road to Boston, but, @cosenal or @vprusso, please go ahead and fix the merge, if you can, or I'll try to do after my talk at Harvard.

Copy link
Contributor

@vprusso vprusso left a comment

Choose a reason for hiding this comment

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

LGTM. Mostly minor comments and a question.

pennylane_qrack/qrack_device.py Outdated Show resolved Hide resolved
pennylane_qrack/qrack_device.py Show resolved Hide resolved
pennylane_qrack/qrack_device.py Show resolved Hide resolved
@mudit2812
Copy link
Contributor

mudit2812 commented Oct 29, 2024

Hey @WrathfulSpatula . Based on the changes in this PR, it looks to me like no changes might be needed on the PennyLane side to get the noisy circuit functionality to work with native Python on the qrack simulator. Could you test the ZNE demo against this branch and let me know if that's the case? We need to know soon so that we know how to proceed. If the demo does not work with just the changes in this PR, my preference would be for us to have a meeting at your earliest convenience to try and understand what is needed.

@Alex-Preciado
Copy link
Contributor

Thanks, @WrathfulSpatula ! Just to add, we'd need to know as soon as possible if any issues remain after testing the demo against this branch. If it's still not working, the best approach would be to schedule a meeting first thing tomorrow to figure out a path forward and ensure this is fixed as soon as possible this week, ahead of our Monday release. We have a couple of alternatives in mind. Let us know if that works for you!

@WrathfulSpatula
Copy link
Collaborator Author

WrathfulSpatula commented Oct 30, 2024

@mudit2812 @Alex-Preciado Thanks for checking in! Apologies, I spoke at Harvard last night, and it's roughly a 5 hour drive for me, each way, to get there and back. Due to an unforeseen issue, I also had no laptop, overnight. (I opened this PR on a phone!) However, yes, this should fix the tutorial without modifying PennyLane. However, it implies that we should follow this same approach for Catalyst, and that's the part that just isn't friendly to (C++) back end developers. I'll take another look at the Catalyst side after lunch.

@WrathfulSpatula WrathfulSpatula merged commit ef5e251 into master Oct 30, 2024
1 check passed
@WrathfulSpatula WrathfulSpatula deleted the one_shot_noisy_back_end branch October 30, 2024 18:28
@cosenal
Copy link
Contributor

cosenal commented Oct 30, 2024

@WrathfulSpatula Wrt:Catalyst, didn't @rmoyard showed to us how in the IR you have each call to circuit using a device with a single shot? Why do you think it's going to be an issue on Catalyst too?

@rmoyard
Copy link
Contributor

rmoyard commented Oct 30, 2024

@cosenal I agree there is no issue with Catalyst, as the produced IR calls the device n times with 1 shot

@Alex-Preciado
Copy link
Contributor

Alex-Preciado commented Oct 31, 2024

Hi team, have you had a chance to verify that the ZNE tutorial works with these changes? We tried testing on our end, but we couldn’t find instructions on how to build the plugin correctly. We’re encountering some errors, but likely due to local build issues while attempting to make the plugin work locally by patching it.

We need to address any outstanding issues by tomorrow, Friday, at 5:00 PM (EST) to stay on track for our Monday release.

@WrathfulSpatula
Copy link
Collaborator Author

@Alex-Preciado yes, we have tested the tutorial with the latest pennylane and pennylane-catalyst builds on TestPy. @cosenal tuned the parameters a bit, now that we finally have the noisy device stack working from end to end, and this was an example of output:

Ideal value: 1.0
Error without mitigation: 0.900
Error with ZNE in Catalyst: 0.225
Error with ZNE in PennyLane: 1.042
mitigated_circuit running time (best of 5): 10.539s
mitigated_circuit_qjit running time (best of 5): 4.093s

There seems to be a divergence between PennyLane and Catalyst ZNE results. However, the "Error without mitigation" line is also from PennyLane rather than Catalyst, indicating that QrackDevice noise is working as expected with this work-around in this PR, for differences between mcm_method="one-shot" between PennyLane and Catalyst. (Once again, pennylane-qrack does not require mcm_method="one-shot" to work with PennyLane, at this point, but this "mixed" solution remains compatible with the setting used for Catalyst. The PennyLane Qrack back end simply ignores "one-shot" but handles what we needed it for via this PR.)

@mudit2812
Copy link
Contributor

However, the "Error without mitigation" line is also from PennyLane rather than Catalyst, indicating that QrackDevice noise is working as expected with this work-around in this PR, for differences between mcm_method="one-shot" between PennyLane and Catalyst.

But it looks like the error with native Pennylane is higher than the error without mitigation. Is that expected?

@cosenal
Copy link
Contributor

cosenal commented Nov 1, 2024

I tested it with the following example, which is simpler than the one in the tutorial, and I consistently get results that make sense to me. This is focused only on PennyLane, not Catalyst.

import numpy as np
from functools import partial
from pennylane import qnode
import pennylane as qml

from pennylane.transforms import fold_global, poly_extrapolate

n_wires = 2

dev = qml.device("qrack.simulator", n_wires, shots=100, noise=0.1)
@partial(
    qml.transforms.mitigate_with_zne,
    scale_factors=[1, 3, 5],
    folding=fold_global,
    extrapolate=poly_extrapolate,
    extrapolate_kwargs={'order': 2})
@qnode(dev)
def circuit():
    qml.PauliX(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.expval(qml.PauliZ(0))

print(circuit())

Output

In the three example runs below, first line is exp values of scaled circuits, second line is after extrapolation.
I also tested the extrapolation in isolation against the reference Mitiq implementation, and it matches perfectly.

Noiseless scenario (noise=0.0)

[array(-1.), array(-1.), array(-1.)]
-0.9999999999999872

Noisy scenario (noise=0.1)

Run 1:

[array(-0.86), array(-0.7), array(-0.42)]
-0.8949999999999915

Run 2:

[array(-0.86), array(-0.58), array(-0.46)]
-1.0599999999999883

Run 3:

[array(-0.86), array(-0.68), array(-0.54)]
-0.9649999999999892

@WrathfulSpatula
Copy link
Collaborator Author

The tutorial now gives me this output, for example (verbatim, on my laptop with a discrete NVIDIA GPU):

Device #0, Loaded binary from: /home/iamu/.qrack/qrack_ocl_dev_NVIDIA_GeForce_RTX_3080_Laptop_GPU.ir
Default platform: NVIDIA CUDA
Default device: #0, NVIDIA GeForce RTX 3080 Laptop GPU
OpenCL device #0: NVIDIA GeForce RTX 3080 Laptop GPU
Ideal value: 1.0
Error without mitigation: 0.818
An NVIDIA GPU may be present on this machine, but a CUDA-enabled jaxlib is not installed. Falling back to cpu.
Error with ZNE in Catalyst: 0.790
Error with ZNE in PennyLane: 0.769
mitigated_circuit running time (best of 5): 139.959s
mitigated_circuit_qjit running time (best of 5): 53.243s

This looks correct. I think we're set!

@cosenal
Copy link
Contributor

cosenal commented Nov 1, 2024

@Alex-Preciado @mudit2812 I am not going to merge the tutorial yet, but you can go ahead with your Monday release.

@mudit2812
Copy link
Contributor

Thanks for confirming! Glad to see it working.

@Alex-Preciado
Copy link
Contributor

Nice! Thanks for the updates @cosenal, @WrathfulSpatula !! Let us know if there's anything else we can do to support.

@Alex-Preciado
Copy link
Contributor

The tutorial now gives me this output, for example (verbatim, on my laptop with a discrete NVIDIA GPU):
...
Error without mitigation: 0.818
Error with ZNE in Catalyst: 0.790
Error with ZNE in PennyLane: 0.769
mitigated_circuit running time (best of 5): 139.959s
mitigated_circuit_qjit running time (best of 5): 53.243s
...
This looks correct. I think we're set!

@WrathfulSpatula I don’t have the necessary context here, but the errors with and without mitigation seem pretty similar. Is this the expected outcome?

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.

6 participants