-
Notifications
You must be signed in to change notification settings - Fork 9
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
feature: add support for typecasting #27
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for starting this! I've left a few comments/suggestions to help debug. Of course you'll want to add unit tests once the code is working, but that can be saved for a later iteration.
By the way, in case it's useful you can enable verbose autograph output via environment variable, e.g. you can do this in a Jupyter notebook cell:
%env AUTOGRAPH_VERBOSITY 10
This will print out the intermediate transpiled program when you call build()
on an AutoQASM program - I find this very useful when working on converters.
I added 3 unit tests but I was not sure if they should go into |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it's on the right track! A few more comments/suggestions here.
test/unit_tests/autoqasm/test_api.py
Outdated
expected_ir = """OPENQASM 3.0; | ||
qubit[2] __qubits__; | ||
bit[2] __bit_0__ = "00"; | ||
__bit_0__[0] = measure __qubits__[0]; | ||
__bit_0__[1] = measure __qubits__[1];""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't look right. I would expect the output IR to contain something like:
int[32] __int_1__ = __bit_0__;
int[32] test = 2 * __int_1__;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For debugging, might be interesting to know what the IR output is if you modify the program to be like this:
@aq.main(num_qubits=2)
def main():
test = int(2 * measure([0, 1]))
or like this:
@aq.main(num_qubits=2)
def main():
test = 2 * int(measure([0, 1]))
return test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked and using
@aq.main(num_qubits=2)
def main():
test = 2 * IntVar(measure([0, 1]))
results in the same IR. I think the discrepancy came from the fact that the variable test
was not being used after declared. Your second suggestion helped me realize that adding return test
(or other lines that make use of test
) results in an IR with the int[32] lines. I updated the unit test to reflect this.
On a second note, I did not add support for arithmetic operations on BitVara in this PR because I focused on int typecasting. To add the arithmetic operations, would you suggest I add methods like __mul__
and __rmul__
to the BitVar
class (where self
gets casted to an IntVar
) or use a converter to intercept the arithmetic operations and cast the BitVars to IntVars?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, good question. I think it's ok to leave out the arithmetic operations from this PR. I think it's ok (and maybe desirable) that the user must manually cast the BitVar to an int before doing arithmetic on it.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #27 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 47 49 +2
Lines 2057 2090 +33
Branches 343 345 +2
=========================================
+ Hits 2057 2090 +33 ☔ View full report in Codecov by Sentry. |
test/unit_tests/autoqasm/test_api.py
Outdated
@aq.main(num_qubits=2) | ||
def main(): | ||
test = 2 * int(measure([0, 1])) # noqa: F841 | ||
return test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be worth having two versions of this test, one without the return
and one with the return
. In both cases the test
variable should be declared and assigned - it shouldn't matter whether it is used afterward.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added! Could you confirm that in the case where there is no return statement, there should not be an instruction involving the 2 *
. Currently, I am getting:
with return
OPENQASM 3.0;
output int[32] test;
qubit[2] __qubits__;
bit[2] __bit_0__ = "00";
__bit_0__[0] = measure __qubits__[0];
__bit_0__[1] = measure __qubits__[1];
int[32] __int_1__;
__int_1__ = __bit_0__;
test = 2 * __int_1__;
without return
OPENQASM 3.0;
qubit[2] __qubits__;
bit[2] __bit_0__ = "00";
__bit_0__[0] = measure __qubits__[0];
__bit_0__[1] = measure __qubits__[1];
int[32] __int_1__;
__int_1__ = __bit_0__;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's interesting - I still would expect the test
variable to be declared and assigned 2 * __int_1__
there. But functionally it doesn't matter, of course. I expect this would be an issue in the assignment converter and outside the scope of your PR. It shouldn't block moving forward with your changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I can look into this in a new issue/PR? I noticed that
@aq.main(num_qubits=2)
def main():
test = 4 * IntVar(2)
results in
OPENQASM 3.0;
qubit[2] __qubits__;
but
@aq.main(num_qubits=2)
def main():
test = IntVar(2)
leads to
OPENQASM 3.0;
qubit[2] __qubits__;
int[32] test = 2;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if you'd like to look into this separately, that would be great! I'd recommend opening a new issue with those details.
test/unit_tests/autoqasm/test_api.py
Outdated
expected_ir = """OPENQASM 3.0; | ||
qubit[2] __qubits__; | ||
bit[2] __bit_0__ = "00"; | ||
__bit_0__[0] = measure __qubits__[0]; | ||
__bit_0__[1] = measure __qubits__[1];""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, good question. I think it's ok to leave out the arithmetic operations from this PR. I think it's ok (and maybe desirable) that the user must manually cast the BitVar to an int before doing arithmetic on it.
@abidart Probably |
@rmshaffer I pushed a new commit with cosmetic changes based on the review from #29 anticipating similar comments. |
def test_int_typecasting_on_string(): | ||
@aq.main(num_qubits=2) | ||
def main(): | ||
test = int("101", 2) # noqa: F841 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we raise an error, instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @laurencap, thank you so much for the review! My goal with this test was to have a "normal" call to int
within a program to check that the built-in int
function gets called—correctly, with all passed arguments—whenever the first input does not involve a QASM type. Could you explain me how can I change it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this is working as intended, but maybe the confusion could be cleared up by changing the name of the test function to make it more clear what is being tested - e.g. test_int_typecasting_on_python_string_not_captured
Issue #, if available:
Related to #10.
Description of changes:
In an attempt to add support for int and float conversion, I made 3 changes:
The goal is to add a functionality such that the following two compile to the same QASM instructions, or very similar:
Testing done:
int
orfloat
is nested, for examplesyndrome = 2 * int(measure([0,1]))
. I need to fix that.tox -e unit-tests
Merge Checklist
Put an
x
in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your pull request.General
Tests
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.