Skip to content

Commit

Permalink
Check for multiples of pi at op construction time
Browse files Browse the repository at this point in the history
Rather than trying to figure it out before printing.

ffffflake
  • Loading branch information
notmgsk committed Sep 23, 2019
1 parent b9f050c commit 2cc4261
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 6 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Changelog
immediate `float` value. Finally, the `CONVERT` instruction now accepts any valid
memory reference designator (a `MemoryReference`, a string, or a tuple of type
`(str, int)`) for both its arguments (@appleby, gh-1010).
- Fix the interaction between pretty-printing multiples of π and discarding of
parentheses that would lead to incorrect arithmetic expressions (@notmgsk, gh-993).

[v2.11](https://github.com/rigetti/pyquil/compare/v2.10.0...v2.11.0) (September 3, 2019)
----------------------------------------------------------------------------------------
Expand Down
15 changes: 9 additions & 6 deletions pyquil/quilatom.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def format_parameter(element):
if isinstance(element, integer_types) or isinstance(element, np.int_):
return repr(element)
elif isinstance(element, float):
return _check_for_pi(element)
return _expression_to_string(_check_for_pi(element))
elif isinstance(element, complex):
out = ''
r = element.real
Expand Down Expand Up @@ -233,6 +233,8 @@ def format_parameter(element):
return _expression_to_string(element)
elif isinstance(element, MemoryReference):
return element.out()
elif isinstance(element, str):
return element
assert False, "Invalid parameter: %r" % element


Expand Down Expand Up @@ -464,7 +466,8 @@ def fn(a, b):
return a / b

def __init__(self, op1, op2):
super(Div, self).__init__(op1, op2)
super(Div, self).__init__(_check_for_pi(op1) if isinstance(op1, float) else op1,
_check_for_pi(op2) if isinstance(op2, float) else op2)


class Pow(BinaryExp):
Expand All @@ -483,7 +486,7 @@ def __init__(self, op1, op2):
def _expression_to_string(expression):
"""
Recursively converts an expression to a string taking into account precedence and associativity for placing
parenthesis
parentheses.
:param Expression expression: expression involving parameters
:return: string such as '%x*(%y-4)'
Expand Down Expand Up @@ -549,11 +552,11 @@ def _check_for_pi(element):
elif abs(num) == 1 and den == 1:
return sign + "pi"
elif abs(num) == 1:
return sign + "pi/" + repr(den)
return Div(sign + "pi", den)
elif den == 1:
return repr(num) + "*pi"
return Mul(num, "pi")
else:
return repr(num) + "*pi/" + repr(den)
return Mul(num, Div("pi", den))
else:
return repr(element)

Expand Down
11 changes: 11 additions & 0 deletions pyquil/tests/test_quil.py
Original file line number Diff line number Diff line change
Expand Up @@ -1298,3 +1298,14 @@ def test_placeholders_preserves_modifiers():
a = address_qubits(p)

assert a[0].modifiers == g.modifiers


def test_arithmetic_pretty_printing():
import numpy as np
from pyquil.quilatom import _expression_to_string
pi = np.pi
theta = [2]
math = "3 * theta[0] / (2 * pi)"
exp = Program(f"RX({math}) 0")[0].params[0]

assert eval(_expression_to_string(exp)) == eval(math)

0 comments on commit 2cc4261

Please sign in to comment.