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

Fix result representation for TDM programs #493

Merged
merged 11 commits into from
Nov 30, 2020
Merged

Fix result representation for TDM programs #493

merged 11 commits into from
Nov 30, 2020

Conversation

thisac
Copy link
Contributor

@thisac thisac commented Nov 26, 2020

Context:
Currently the representation of the Result object doesn't work for TDM programs due to the samples having dimension 3 (shots, spatial modes, timebins) instead of 2.

Description of the Change:
Quick fix that assumes that it's a TDM program if the samples dim is 3, and thus prints the correct representation.

Benefits:
Just writing eng.run(tdm_prog) or res = eng.run(tdm_prog); print(res) works, and actually prints something useful.

Possible Drawbacks:
Might not be the nicest solution, but since Result doesn't know what type of program the samples are from, I think this works well for now. Might need to be revisited later with some further changes to the Result class (incorporating e.g. where the results are from).

Related GitHub Issues:
None

@thisac thisac changed the title Fix result repr Fix result representation for TDM programs Nov 26, 2020
@codecov
Copy link

codecov bot commented Nov 26, 2020

Codecov Report

Merging #493 (6c32270) into master (2aa4e15) will not change coverage.
The diff coverage is n/a.

@@           Coverage Diff           @@
##           master     #493   +/-   ##
=======================================
  Coverage   97.85%   97.85%           
=======================================
  Files          70       70           
  Lines        7313     7313           
=======================================
  Hits         7156     7156           
  Misses        157      157           
Impacted Files Coverage Δ
strawberryfields/api/result.py 100.00% <ø> (ø)
strawberryfields/engine.py 96.13% <ø> (ø)

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 2aa4e15...6c32270. Read the comment docs.

Comment on lines 126 to 127
return "<Result: spatial_modes={}, shots={}, timebins={} contains state={}>".format(
modes, shots, timebins, self._is_stateful
Copy link
Contributor

Choose a reason for hiding this comment

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

Think this would be good to keep the order from the shape. Let me know if the change in order was deliberate though!

Suggested change
return "<Result: spatial_modes={}, shots={}, timebins={} contains state={}>".format(
modes, shots, timebins, self._is_stateful
return "<Result: shots={}, spatial_modes={}, timebins={} contains state={}>".format(
shots, modes, timebins, self._is_stateful

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I also think this looks nicer to be honest. I just kept the same form as the current repr (for GBS samples) which starts with modes, and then shots. I might just update it in both places if you also think that makes more sense.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, think it's good to keep the shape order. As for changing for GBS, not quite sure if that would cause any troubles somewhere (don't think so) 🤔.

shots, modes = self.samples.shape
try:
shots, modes = self.samples.shape
except ValueError:
Copy link
Contributor

Choose a reason for hiding this comment

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

Think this would work fine for now actually! 💯 Would be great to add a test though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @antalszava. I've added a test now! You were a bit too quick (and I maybe tagged you for a review a bit too quickly). 😆

Copy link
Contributor

@antalszava antalszava left a comment

Choose a reason for hiding this comment

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

Hi @thisac the fix is looking great! A test might be nice and then I think it should be good to go.

result = Result(samples)
print(result)
out, err = capfd.readouterr()
assert "spatial_modes=3" in out
Copy link
Contributor

Choose a reason for hiding this comment

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

💯 Might be cool to check the order (not too important though).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this is fine (since the order isn't actually that important I would say).

Copy link
Contributor

@antalszava antalszava left a comment

Choose a reason for hiding this comment

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

Looks good to me! 💯

Co-authored-by: antalszava <antalszava@gmail.com>
Copy link
Member

@josh146 josh146 left a comment

Choose a reason for hiding this comment

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

Thanks @thisac - just a small comment regarding the existing try-except logic

.github/CHANGELOG.md Outdated Show resolved Hide resolved
Result: 3 subsystems
state: <GaussianState: num_modes=3, pure=True, hbar=2>
samples: [[0, 0, 0]]
<Result: shots=1, num_modes=3, contains state=True>
Copy link
Member

Choose a reason for hiding this comment

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

Good catch, was this accidentally out of date?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes it was, not sure why.

modes, shots, self._is_stateful
try:
shots, modes = self.samples.shape
except ValueError:
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if there is something better we can catch here than a ValueError, since this exception class is a very common class that could be raised for a whole different host of (unforseen) reasons.

I'm thinking checking the number of dimensions on the samples should be sufficient, e.g.,

def __repr__(self):

    if self.samples.ndim == 2:
        shots, modes = self.samples.shape
        return "<Result: shots={}, num_modes={}, contains state={}>".format(shots, modes, self._is_stateful)

    if self.samples.ndim == 3:
        shots, modes, timebins = self.samples.shape
        return "<Result: shots={}, spatial_modes={}, timebins={} contains state={}>".format(
            shots, modes, timebins, self._is_stateful
        )

    return "<Result: contains state={}>"

Copy link
Member

Choose a reason for hiding this comment

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

This has a couple of advantages from what I can see:

  • It is explicit

  • It avoids catching ValueError exceptions, which are too general

  • If there are changes in the future, it will not break printing; it will gracefully fail without attempting to print sample information.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks @josh146. I think this is a good solution as well. Updated it to follow your logic above and added a test.

Comment on lines 600 to 601
[strawberryfields.api.Result, None]: the job result if successful, and
``None`` otherwise
``None`` otherwise
Copy link
Member

Choose a reason for hiding this comment

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

Typically we do not indent continuation lines in the returns statement, it will cause Sphinx to render the block incorrectly. Only continuation lines in the Args: section need to be indented.

Moreover, it's a bit weird that there are square brakets here; it should look like this:

strawberryfields.api.Result, None: the job result if successful or ``None`` otherwise

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, I didn't actually know. Fixed now!

thisac and others added 2 commits November 27, 2020 09:48
Co-authored-by: Josh Izaac <josh146@gmail.com>
@thisac thisac requested a review from josh146 November 27, 2020 15:00
Copy link
Member

@josh146 josh146 left a comment

Choose a reason for hiding this comment

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

Looks great! 💯

strawberryfields/api/result.py Outdated Show resolved Hide resolved
Comment on lines +71 to +73
def test_unkown_shape_print(self, stateful, capfd):
"""Test that printing a result object with samples with an unknown shape
provides the correct output."""
Copy link
Member

Choose a reason for hiding this comment

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

Nice!

thisac and others added 2 commits November 30, 2020 11:51
Co-authored-by: Josh Izaac <josh146@gmail.com>
@thisac thisac merged commit 75e3c26 into master Nov 30, 2020
@thisac thisac deleted the fix-result-repr branch November 30, 2020 22:17
@thisac thisac self-assigned this Nov 30, 2020
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.

3 participants