XanaduAI / strawberryfields

Strawberry Fields is a full-stack Python library for designing, simulating, and optimizing continuous variable (CV) quantum optical circuits.
https://strawberryfields.ai
Apache License 2.0
745 stars 187 forks source link

[WIP] Bosonic backend support for threshold measurement #604

Closed JeyKelly closed 3 years ago

JeyKelly commented 3 years ago

Context: Currently, the Bosonic backend does not support the MeasureFock and MeasureThreshold measurement operations. This pull request aims to add support for it. Ref : issue #571

Description of the Change: Adding support for measure_threshold and measure_fock

Benefits:

Possible Drawbacks: N/A

Related GitHub Issues:

josh146 commented 3 years ago

Thanks @JeyKelly for this PR! Feel free to ask any questions here, and you can comment directly on the code itself 🙂

JeyKelly commented 3 years ago

@josh146 I've checked the result of the test and it seems like the test was designed to raise a non-implemented error when calling the MeasureThreshold operation (~strawberryfields\tests\backend\test_bosonic_backend.py line 664). Assuming the Fock state case works and post-measurement is updated properly, should I update the pull request to include removing the line of code and adding two extra modes to test_measurement verifying the proper sample shapes/states after applying MeasureFock and MeasureThreshold?

JeyKelly commented 3 years ago

@nquesada I have revisited the measure_threshold method in the way you suggested. I have ran into a few issues when testing, and this is why I didn't update the test file yet. If I ran the circuit with a Fock() state parameter of 7, the circuit returns nan values for the weights (hence can't even run without a measurement), and if I put more, the fidelity of vacuum is bigger than one. This doesn't seem to be related to these modifications, but I thought I would mention it before creating an automatic test for the measurement.

That being said, the measure_fock method still remains and I'm not sure on how to approach updating the state (and even if the measurement is done properly). Do you have a similar piece theory that would help achieve this one?

nquesada commented 3 years ago

Hi @JeyKelly --- The PR is looking really nice. For tests I'd suggest a few:

JeyKelly commented 3 years ago

Hi @JeyKelly --- The PR is looking really nice. For tests I'd suggest a few:

* Prepare the vacuum and check that when you use threshold measurements you never get a click.

* Prepare the odd cat states (with `p=1`) and also verify that you never get click.

* This somewhat trivial, but check that the shapes of the covariances and vectors of means are correct when you get a click/no click.

@nquesada Hi, thanks for the response. Just to be sure, do you mean for automatic tests?

nquesada commented 3 years ago

Hi @JeyKelly --- Yes, I mean automatic tests. You can start by using the backend independent tests here:

https://github.com/XanaduAI/strawberryfields/blob/master/tests/backend/test_threshold_measurement.py

To test the bosonic backend it should be as easy as adding "bosonic:" in this line: https://github.com/XanaduAI/strawberryfields/blob/afde2997ce04d44612232be2a354946f608c0a7f/tests/backend/test_threshold_measurement.py#L24

nquesada commented 3 years ago

Then you could add tests specific to the bosonic backend in here https://github.com/XanaduAI/strawberryfields/blob/master/tests/bosonic_files/test_backend_bosoniccircuit.py

This could be the ones I described before involving cat states and the ones checking the shapes of the updated coefficients, vectors of means and covariance matrices are correct.

JeyKelly commented 3 years ago

To test the bosonic backend it should be as easy as adding "bosonic:" in this line:

https://github.com/XanaduAI/strawberryfields/blob/afde2997ce04d44612232be2a354946f608c0a7f/tests/backend/test_threshold_measurement.py#L24

Hi Again @nquesada, by using the test test_two_mode_squeezed_measurements in this file, it made me realize that running the circuit with two identical squeezed state (on two uninteracting modes) and measuring them gives me a different result. It seems that the self.fidelity_vacuum() is the culprit. Multiple calls to the function in one program increments its value when the state gets updated post-measurement (namely the self.weights) on uninteracting modes, when there is "no click" ("clicks" measurements decrease the weights so it doesn't seem to run into problems). I'm not sure if the problem lies in the use of it in the code I submitted here or if the function itself has a flaw, but this prevents running the test because the vacuum fidelity goes above one in this case. Like I've mentioned previously, the fidelity is also problematic (above one) when calculated on a Fock state of more than 7 photons, even on a clean version of strawberryfields.

nquesada commented 3 years ago

Hi @JeyKelly --- That is because two-mode squeezing is different from applying single-mode squeezing in two modes. As for your second question, you are correct that Fock states have a number of numerical issues. For the moment I suggest you set them aside (both in terms of preparing them or measuring them) and focus in threshold detection. Let's worry about Fock measurements in a future PR.

JeyKelly commented 3 years ago

Hi @JeyKelly --- That is because two-mode squeezing is different from applying single-mode squeezing in two modes.

@nquesada Yes, but I ran into fidelity problems by running the single-mode squeezing in two modes while trying to see where the problem was for two-mode squeezing (sorry, it might have been superfluous to mention it). Vacuum fidelity of the remaining mode increases (above 1) when there is a "no click" event in the first single-mode squeezed state.

nquesada commented 3 years ago

Can you share a minimal non-working example of the issue you are finding with the two single-mode squeezed states @JeyKelly ?

JeyKelly commented 3 years ago

Can you share a minimal non-working example of the issue you are finding with the two single-mode squeezed states @JeyKelly ?

import strawberryfields as sf

hbar = 2
nmodes = 2

prog_cat_fock = sf.Program(nmodes)
with prog_cat_fock.context as q:
    sf.ops.Catstate(alpha=0.1)   | q[0]    
    sf.ops.Catstate(alpha=0.1)   | q[1]         
    sf.ops.MeasureThreshold()    | q[0]   
    sf.ops.MeasureThreshold()    | q[1]   

eng = sf.Engine("bosonic", backend_options={"hbar": hbar})
result = eng.run(prog_cat_fock)

@nquesada This will do the trick, or any combination of state close to unity vacuum fidelity (for example, by replacing both states with sf.ops.Squeezed(r=0.1)). When the weights are adjusted here post "no-click" with the c' = c/p0 line, vacuum_fidelity exceeds 1 when calculated for the q[1] mode.

codecov[bot] commented 3 years ago

Codecov Report

Merging #604 (da7cbd7) into master (45309dc) will not change coverage. The diff coverage is n/a.

@@           Coverage Diff           @@
##           master     #604   +/-   ##
=======================================
  Coverage   98.56%   98.56%           
=======================================
  Files          77       77           
  Lines        8904     8904           
=======================================
  Hits         8776     8776           
  Misses        128      128           

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 45309dc...da7cbd7. Read the comment docs.

nquesada commented 3 years ago

@elib20 : I take the point that it should be equivalent to heterodyne post selected on the \alpha = 0 outcome. But this implementation is still correct. I guess it is hard to see how one is equivalent to the other since heterodyne calls generaldyne. Is your point that more tests should be added? Or that I should use reuse the functionality from heterodyne for the no click case here?