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

Arrays as parameters #34

Merged
merged 35 commits into from
Oct 28, 2020
Merged

Arrays as parameters #34

merged 35 commits into from
Oct 28, 2020

Conversation

thisac
Copy link
Contributor

@thisac thisac commented Oct 19, 2020

Arrays cannot currently be written as parameters in a template, which is needed for the TDM experiments.

What's been changed?

  • Arrays now support being defined as parameters (with braces); see example below.
  • Parameters can be assigned to variables (e.g. int number = {par})
  • Calling a Blackbird template with template parameter values now need to include parameters defined outside of circuits, which wasn't possible before.

With the changes in this PR, it will be possible to write something like the following:

name template_tdm
version 1.0
target tdm (shots=1)
type tdm (temporal_modes=3, copies=1)

float array p0[1, 3] =
    {bs_array}

float array p1[1, 3] =
    {r_array}

float array p2[1, 3] =
    {b_array}

Sgate(1, 0) | 1
BSgate(p0) | (1, 0)
Rgate(p1) | 1
MeasureHomodyne(p2) | 0

Potential issues
There's no validation done on the variables/arrays when assigning values to template parameters. Thus, it is possible to assign e.g. a float to {par} in int number = {par}, since the type validation is only done at parsing, and the template parameter assignment is done separately, after the parsing, without knowing the type.

@codecov
Copy link

codecov bot commented Oct 19, 2020

Codecov Report

Merging #34 into master will increase coverage by 0.13%.
The diff coverage is 98.24%.

@@            Coverage Diff             @@
##           master      #34      +/-   ##
==========================================
+ Coverage   96.94%   97.07%   +0.13%     
==========================================
  Files          12       12              
  Lines        1704     1849     +145     
==========================================
+ Hits         1652     1795     +143     
- Misses         52       54       +2     
Impacted Files Coverage Δ
blackbird_python/blackbird/auxiliary.py 99.31% <85.71%> (-0.69%) ⬇️
blackbird_python/blackbird/listener.py 99.58% <97.29%> (-0.42%) ⬇️
blackbird_python/blackbird/program.py 99.48% <98.38%> (-0.52%) ⬇️
blackbird_python/blackbird/tests/test_auxiliary.py 100.00% <100.00%> (ø)
blackbird_python/blackbird/tests/test_listener.py 100.00% <100.00%> (+0.30%) ⬆️
blackbird_python/blackbird/tests/test_program.py 100.00% <100.00%> (ø)

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 fccaab1...54321e2. Read the comment docs.

@thisac thisac self-assigned this Oct 20, 2020
@thisac thisac requested a review from josh146 October 21, 2020 03:50
@thisac thisac requested a review from antalszava October 21, 2020 17:45
Comment on lines 269 to 270
for i, row in enumerate(v):
for j, col in enumerate(row):
Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nice, I didn't know about this. Not sure if I think it would be an improvement in this case though. 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Also came across it just now! The improvement for me would be readability (could be subjective), as there are many nested blocks around here and also it would be helpful to see that indeed the loops are used for indexing only

Copy link
Member

Choose a reason for hiding this comment

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

👍 for np.ndindex, it's quite neat :)

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, this looks overall nice to me! 💯 🙂 Left suggestions & questions, mostly aiming at code quality. I think the tests should mostly cover the use case that we'd like to have

@thisac thisac marked this pull request as ready for review October 22, 2020 00:17
@thisac thisac requested review from josh146 and antalszava October 27, 2020 16:36
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.

@thisac this is looking much better now I think! The serialization test is also awesome.

My only comments were with respect to the p\d variables; probably better if the change in behaviour was restricted to only tdm programs, to avoid potentially breaking existing GBS blackbird scripts

array_insert += 1
options = ""
# add target and type to the script
for name, data in [("target", self.target), ("type", self.programtype)]:
Copy link
Contributor

Choose a reason for hiding this comment

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

I found it difficult at first to parse this loop, may be worth checking how the code would look by adding target & type sequentially? Imho, a couple of lines duplicated lines could be fine

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would it be nicer to instead add a separate function e.g. self.add_metadata("target") and self.add_metadata("type")?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looking at it again, I actually think I prefer this solution; without adding it sequentially (or creating separate functions).

antalszava
antalszava previously approved these changes Oct 27, 2020
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 awesome @thisac! 🥇 🚀 🙂 Most of the thoughts from me are smaller and related to readability. One thing I was wondering about related to the test that has a script, is if target would be missing.

Maybe something for the PR regarding docs: adding a note on which parameter names are reserved for TDM can be nice.


# line break
script.append("")

# add variables to the script
Copy link
Contributor

Choose a reason for hiding this comment

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

Personally, would be in for separating parts of this method into multiple smaller methods (e.g., here having this as add_variables). (Commenting here, as this part of the method is newly added in this PR.)

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 fully agree with this. 💯 I feel like this is the case for quite a few parts of the Blackbird code, so actually a refactor, that simply splits many parts of the code into sub-functions, would be really nice. Maybe this can be added separately as a refactor PR some time? What do you think @josh146?

Copy link
Member

Choose a reason for hiding this comment

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

I agree! Definitely something that would be great to improve

# add variables to the script
if self.programtype["name"] == "tdm":
from .listener import NUMPY_TYPES # pylint:disable=import-outside-toplevel
inv_type_map = {np.dtype(v).kind: k for k, v in NUMPY_TYPES.items()}
Copy link
Contributor

Choose a reason for hiding this comment

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

(Minor suggestions:) this seems to be something that could be generally used, how about having it in listener.py (e.g., after the def of NUMPY_TYPES)?

Comment on lines 342 to 350
for k, v in self._var.items():
var_type = inv_type_map[np.array(v).dtype.kind]
array_string = ""
if isinstance(v, np.ndarray):
for row in v:
array_string += "\n " + "".join("{}, ".format(i) for i in row)[:-2]
script.append("{} array {} ={}".format(var_type, k, array_string))
else:
script.append("{} array {} ={}".format(var_type, k, v))
Copy link
Contributor

Choose a reason for hiding this comment

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

💯

Comment on lines +431 to +433
kwargs.append("{}={}".format(k, v))
else:
kwargs.append('{}="{}"'.format(k, v))
Copy link
Contributor

Choose a reason for hiding this comment

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

(Minor suggestion): the difference between the two expressions is minor. It could help the reader if the value was extracted somehow to show the difference (not sure if this the suggestion is much better though 😅)

                        if self.programtype["name"] == "tdm" and v[0] == "p" and v[1:].isdigit():
                            value = "{}".format(v)
                        else:
                            value = '"{}"'.format(v)
                        kwargs.append("{}={}".format(k, value))

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 might just keep this as it is now. I think it's clear enough, although I see your point. 🙂

expected = dedent(
"""\
name tdm
version 1.0
Copy link
Contributor

Choose a reason for hiding this comment

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

Would we need a target field too here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Target isn't mandatory in a Blackbird script, so it's not needed (but wouldn't change anything).

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we have it in here? Just as a sanity check, as most TDM bb scripts would have it


This release contains contributions from (in alphabetical order):

Theodor Isacsson
Copy link
Member

Choose a reason for hiding this comment

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

The changelog is looking great 😍

josh146
josh146 previously approved these changes Oct 28, 2020
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.

💯 🔥 Great work @thisac

Comment on lines +397 to +401
# if a p-type parameter is used in a tdm program, it would be considered
# a free parameter (stored in `_PAR`) and thus shouldn't be set with a
# value during expression evaluation; although, since it always has an
# accompanying variable it also needs to be stored in `_VAR` with its
# corresponding value
Copy link
Member

Choose a reason for hiding this comment

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

👍

@thisac thisac merged commit 9c09a0d into master Oct 28, 2020
@thisac thisac deleted the arrays-as-parameters branch October 28, 2020 18:32
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