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
754 stars 191 forks source link

Added Parity Expectation #389

Closed Lucaman99 closed 4 years ago

Lucaman99 commented 4 years ago

Context:

Implements changes outlined in Strawberry Fields such that https://github.com/XanaduAI/pennylane/issues/193 can be eventually resolved.

Description of the Change:

Added a parity_expectation function, which takes the index of one qumode as an argument and outputs <(-1)^N> for the given mode (where N is the number operator). Currently is implemented in the BaseFockState class (not the BaseGaussianState class yet). It also only currently supports pure states and only has one "basic" unit test associated with it.

I was hoping to get a bit of feedback (to make sure I'm not making any big mistakes) before I proceed, hence the WIP pull request. πŸ™‚

Benefits:

Benefits are outlined in https://github.com/XanaduAI/pennylane/issues/193.

Possible Drawbacks:

None that I can think of.

Related GitHub Issues:

https://github.com/XanaduAI/pennylane/issues/193

Lucaman99 commented 4 years ago

@nquesada Thanks, I just realized that.all_fock_probs works for mixed states as well (for some reason I thought it didn't), so it should support mixed states now!

codecov[bot] commented 4 years ago

Codecov Report

Merging #389 into master will increase coverage by 0.00%. The diff coverage is 100.00%.

@@           Coverage Diff           @@
##           master     #389   +/-   ##
=======================================
  Coverage   97.78%   97.79%           
=======================================
  Files          54       54           
  Lines        6468     6475    +7     
=======================================
+ Hits         6325     6332    +7     
  Misses        143      143           
Impacted Files Coverage Ξ”
strawberryfields/apps/__init__.py 100.00% <100.00%> (ΓΈ)
strawberryfields/apps/train/__init__.py 100.00% <100.00%> (ΓΈ)
strawberryfields/apps/train/embed.py 100.00% <100.00%> (ΓΈ)
strawberryfields/backends/states.py 97.03% <100.00%> (+0.05%) :arrow_up:

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 77aaa83...e5a15a3. Read the comment docs.

nquesada commented 4 years ago

Hey @Lucaman99, adding expectations of parity operators is a great idea. I would like to suggest the following: Instead of implementing it from scratch we can re-purpose code already in SF. In this file https://github.com/XanaduAI/strawberryfields/blob/master/strawberryfields/backends/states.py we define the function number_expectation. If you have a look at this function you quickly realize that if in line https://github.com/XanaduAI/strawberryfields/blob/1698b95902a149fced9f3a19783a3f9e8019185f/strawberryfields/backends/states.py#L897 you change the value of the parameter values to be (-1)**np.arange(cutoff) you can use the function to calculate the expectation values of the product of the parity operator over as many modes as you wish, with the advantage that this function already works for Numpy and TensorFlow.

This I'd suggest the following

  1. Take the logic of the function number_expectation and put it in a new function called diagonal_expectation that takes values as a parameter. This function will be useful to calculate expectation values of any operator that is diagonal in the number basis.
  2. Have number_expectation call diagonal_expectation with values = np.arange(cutoff).
  3. Create a new function called parity_expectation that calls diagonal_expectation with values = (-1)**np.arange(cutoff).
  4. Write tests, similar to the ones here https://github.com/XanaduAI/strawberryfields/blob/1698b95902a149fced9f3a19783a3f9e8019185f/tests/backend/test_states.py#L85

Finally, I think one can also write in a reasonably simple form the expectation of the parity for a Gaussian state. Maybe after you do it for the Fock representation I can add the parity expectation for Gaussian states.

Hope this makes sense, and let me know if you have questions!

nquesada commented 4 years ago

Quick update: For Gaussian states the expectation value of the parity is just the value of the Wigner function at the origin, you just need to obtain the vector of means r and the covariance matrix V of the modes that you are interested in and calculate np.exp(-0.5*r@np.linalg.inv(V)@r)/np.sqrt(np.linalg.det(V)) and you will get what you want.

Lucaman99 commented 4 years ago

@nquesada Thanks for the suggestions. This all makes sense, I'll get to work on implementing these changes right away!

Lucaman99 commented 4 years ago

@nquesada In addition to the parity operator, do you think it would make sense to add some other functions that return expectation values of other "useful" operators that are diagonal in the Fock basis (for instance, a specified order-two polynomial of the form aN^2 + bN + c, with N being the number operator) by utilizing the functionality of the diagonal_expectation?

Lucaman99 commented 4 years ago

Also, relating to this, do you think it would be better to take a function that acts on np.arrange(cutoff) rather than an array of values as an argument so that it might be more intuitive for a user to use diagonal_expectation to calculate the expectation of some operator of the form f(N)?

nquesada commented 4 years ago

Great! @Lucaman99 ,that is an interesting design question, I'd be tempted to keep the values, but maybe there are reasons to make it "functional".

Lucaman99 commented 4 years ago

@nquesada Yeah, I'm definitely no expert at code design, so if you think it's best to keep it as values then let's do that!

Lucaman99 commented 4 years ago

@nquesada Just made the changes to the Fock backend version, will add tests and Gaussian version tomorrow!

Lucaman99 commented 4 years ago

@nquesada Just pushed changes the re-define number_expectation. Working on the tests right now. Also, I added a function that calculates "quadratic expectation" (EV of an operator of the form aN^2 + bN + c), as per my comment from a couple of days ago. If you don't think it is useful, let me know and I'll delete it. πŸ‘

nquesada commented 4 years ago

Here are a few tests you could add:

  1. For a coherent state with parameter \alpha and defining its mean photon number as m = |\alpha|^2 the expectation of the parity is \exp(-2m)
  2. For a single mode squeezed vacuum the parity is always 1.
  3. For two-mode squeezed vacuum the expectation of the product of the two parities is also 1.
nquesada commented 4 years ago

Also, for a thermal state with mean photon number m, the parity is 1/(2m+1)

Lucaman99 commented 4 years ago

@nquesada Awesome thanks

Lucaman99 commented 4 years ago

@nquesada Done with the tests, let me know what you think.

nquesada commented 4 years ago

Before review Jack, please make sure to remove these files:

image

and then, solve any issues detected by code factor:

image

Lucaman99 commented 4 years ago

@nquesada Will do πŸ‘

Lucaman99 commented 4 years ago

@nquesada Ok, CodeFactor seems to be working, I don't really know why the Formatting check is failing.

nquesada commented 4 years ago

You need to check the formatting in states.py:

image

Also try to update to the latest version of black

Lucaman99 commented 4 years ago

@nquesada Ok, I think I've finally figured out why the Travis tests are failing: the cutoff dimension of the states created by the backend in test_states.py is way too low to be compared to the exact values. Is there any way I can change this for the one particular class in which the parity tests are located?

Sorry this is taking so long, hopefully this change works.

Lucaman99 commented 4 years ago

Nevermind, just realized I was setting the parameters in the tests to absurdly high values (relative to the set cutoff).

josh146 commented 4 years ago

Nevermind, just realized I was setting the parameters in the tests to absurdly high values (relative to the set cutoff).

Yep, it's a bit of a tradeoff πŸ™‚ We want a low cutoff so that the tests complete in a meaningful time, which means we need to choose relatively small values of squeezing and displacement. For the formatting check, the following should fix it as @nquesada suggests:

pip install black --upgrade
black -l 100 strawberryfields/

(The version of Black we use is black==19.10b0).

nquesada commented 4 years ago

Hi @Lucaman99 , almost there! The test are failing because Travis is trying to run them in the Gaussian backend for which we have not implemented parity. You need to mark the tests you wrote for the parity so that they are only run in Fock and TF backends, like it is currently done for number operator. Also, it might be simpler if you run pytest on the test file you have locally, that way you can see how the test are failing before having to wait for Travis.

nquesada commented 4 years ago

@Lucaman99 you also need to update the CHANGELOG adding an entry for this new functionality and your name to the author list.

Lucaman99 commented 4 years ago

@nquesada Alright, done! Travis worked for the most recent changes to the tests file, so all the tests should pass!

Lucaman99 commented 4 years ago

@antalszava Done!