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

exponential_map checks values of closed-over variable inside closure #1055

Open
2 tasks done
jlapeyre opened this issue Oct 16, 2019 · 4 comments
Open
2 tasks done

exponential_map checks values of closed-over variable inside closure #1055

jlapeyre opened this issue Oct 16, 2019 · 4 comments
Labels
bug 🐛 An issue that needs fixing.

Comments

@jlapeyre
Copy link
Contributor

jlapeyre commented Oct 16, 2019

Pre-Report Checklist

  • I am running the latest versions of pyQuil and the Forest SDK
  • I checked to make sure that this bug has not already been reported

Issue Description

Insert a short description of the bug here, along with what you expected the behavior to be.

Thanks for helping us improve pyQuil! 🙂

How to Reproduce

If useful, provide a numbered list of the steps that result in the error.

Otherwise, just fill out the "Code Snippet" and "Error Output" sections below.

Code Snippet

Include a snippet of the pyQuil code that produces the error here.

Error Output

Additionally, please copy and paste the output of the above code here.

Environment Context

Operating System:

Python Version (python -V):

Quilc Version (quilc --version):

QVM Version (qvm --version):

Python Environment Details (pip freeze or conda list):

Copy and paste the output of `pip freeze` or `conda list` here.
@jlapeyre jlapeyre added the bug 🐛 An issue that needs fixing. label Oct 16, 2019
@jlapeyre
Copy link
Contributor Author

exponential_map takes a parameter and returns a function closing over that parameter. But, the returned function includes conditionals testing the value of the parameter. These conditionals should probably be moved outside the body of the returned function. OTOH, as @appleby mentioned in another channel, the value that is closed over includes mutable attributes, so someone might be relying on this behavior.

pyquil/pyquil/paulis.py

Lines 837 to 864 in 527138b

def exponential_map(term):
"""
Returns a function f(alpha) that constructs the Program corresponding to exp(-1j*alpha*term).
:param term: A pauli term to exponentiate
:returns: A function that takes an angle parameter and returns a program.
:rtype: Function
"""
if not np.isclose(np.imag(term.coefficient), 0.0):
raise TypeError("PauliTerm coefficient must be real")
coeff = term.coefficient.real
term.coefficient = term.coefficient.real
def exp_wrap(param):
prog = Program()
if is_identity(term):
prog.inst(X(0))
prog.inst(PHASE(-param * coeff, 0))
prog.inst(X(0))
prog.inst(PHASE(-param * coeff, 0))
elif is_zero(term):
pass
else:
prog += _exponentiate_general_case(term, param)
return prog
return exp_wrap

@jlapeyre jlapeyre changed the title exponential_map check values of closed-over variable inside closure exponential_map checks values of closed-over variable inside closure Oct 16, 2019
@jlapeyre
Copy link
Contributor Author

jlapeyre commented Oct 16, 2019

We could create a deep copy term, which would effectively make it immutable.

@jlapeyre
Copy link
Contributor Author

jlapeyre commented Feb 24, 2020

  1. The closed-over PauliTerm contains mutable data.
  2. If the data in PauliTerm is in fact not changed after the creation of the closure, then the conditional checks inside the closure are redundant. But, the inefficiency introduced is probably negligible.
  3. A user could rely on mutating the PauliTerm after creating the closure. In that case, moving the conditional checks outside the creation of the closure could break the user's code.
  4. It's very unlikely that the scenario in 3 is actually happening. (I think @ecpeterson said this, and I guess it is correct.)
  5. Closing over a copy of the PauliTerm and moving the conditionals outside of the function creation would make the intent more clear. There is a small chance it would break someone's code. But, that would likely be revealing a bug in that code.

@jlapeyre
Copy link
Contributor Author

jlapeyre commented Feb 24, 2020

This should be addressed together with #373 and #537

jlapeyre added a commit that referenced this issue Feb 25, 2020
* exponential_map of the identity applies a PHASE gate and
its inverse. This was apparently for debugging purposes. This
PR replaces the PHASE gates with an empty Program.

* This PR moves conditionals on data that is closed over from
inside the closure to outside. That is, the gate that is exponentiated
is checked when the closure is created, but not when it is executed.

Closes #1055. This PR obsoletes PR #373.
jlapeyre added a commit that referenced this issue Feb 25, 2020
* exponential_map of the identity applies a PHASE gate and
its inverse. This was apparently for debugging purposes. This
PR replaces the PHASE gates with an empty Program.

* This PR moves conditionals on data that is closed over from
inside the closure to outside. That is, the gate that is exponentiated
is checked when the closure is created, but not when it is executed.

Closes #1055. This PR obsoletes PR #373.
jlapeyre added a commit that referenced this issue Feb 25, 2020
* exponential_map of the identity applies a PHASE gate and
its inverse. This was apparently for debugging purposes. This
PR replaces the PHASE gates with an empty Program.

* This PR moves conditionals on data that is closed over from
inside the closure to outside. That is, the gate that is exponentiated
is checked when the closure is created, but not when it is executed.

Closes #1055. This PR obsoletes PR #373.
jlapeyre added a commit that referenced this issue Feb 25, 2020
* exponential_map of the identity applies a PHASE gate and
its inverse. This was apparently for debugging purposes. This
PR replaces the PHASE gates with an empty Program.

* This PR moves conditionals on data that is closed over from
inside the closure to outside. That is, the gate that is exponentiated
is checked when the closure is created, but not when it is executed.

Closes #1055. This PR obsoletes PR #373.
jlapeyre added a commit that referenced this issue Feb 25, 2020
* exponential_map of the identity applies a PHASE gate and
its inverse. This was apparently for debugging purposes. This
PR replaces the PHASE gates with an empty Program.

* This PR moves conditionals on data that is closed over from
inside the closure to outside. That is, the gate that is exponentiated
is checked when the closure is created, but not when it is executed.

Closes #1055. This PR obsoletes PR #373.
jlapeyre added a commit that referenced this issue Feb 25, 2020
* exponential_map of the identity applies a PHASE gate and
its inverse. This was apparently for debugging purposes. This
PR replaces the PHASE gates with an empty Program.

* This PR moves conditionals on data that is closed over from
inside the closure to outside. That is, the gate that is exponentiated
is checked when the closure is created, but not when it is executed.

Closes #1055. This PR obsoletes PR #373.
jlapeyre added a commit that referenced this issue Feb 26, 2020
* exponential_map of the identity applies a PHASE gate and
its inverse. This was apparently for debugging purposes. This
PR replaces the PHASE gates with an empty Program.

* This PR moves conditionals on data that is closed over from
inside the closure to outside. That is, the gate that is exponentiated
is checked when the closure is created, but not when it is executed.

Closes #1055. This PR obsoletes PR #373.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 An issue that needs fixing.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant