Skip to content

Commit

Permalink
Fix spurious PHASE and conditional in exponential_map
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
jlapeyre committed Feb 25, 2020
1 parent d45246d commit 4205213
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 21 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Changelog
- Fixed the QCS access request link in the README (@amyfbrown, gh-1171).
- Fix the SDK download link and instructions in the docs (@amyfbrown, gh-1173).
- Removed HALT from valid Protoquil / supported Quil. (@kilimanjaro, gh-1176).
- Fix spurious PHASE and conditional in exponential_map (@jlapeyre, gh-1182).

[v2.17](https://github.com/rigetti/pyquil/compare/v2.16.0...v2.17.0) (January 30, 2020)
---------------------------------------------------------------------------------------
Expand Down
25 changes: 12 additions & 13 deletions pyquil/paulis.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
)

from .quil import Program
from .gates import H, RZ, RX, CNOT, X, PHASE, QUANTUM_GATES
from .gates import H, RZ, RX, CNOT, QUANTUM_GATES
from numbers import Number
from collections import OrderedDict
import warnings
Expand Down Expand Up @@ -920,21 +920,20 @@ def exponential_map(term: PauliTerm) -> Callable[[float], Program]:
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: float) -> Program:
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:
if is_zero(term) or is_identity(term):

def exp_wrap(param: float) -> Program:
prog = Program()
return prog

else:

def exp_wrap(param: float) -> Program:
prog = Program()
prog += _exponentiate_general_case(term, param)
return prog
return prog

return exp_wrap

Expand Down
12 changes: 9 additions & 3 deletions pyquil/tests/test_paulis.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import numpy as np
import pytest

from pyquil.gates import RX, RZ, CNOT, H, X, PHASE
from pyquil.gates import RX, RZ, CNOT, H
from pyquil.paulis import (
PauliTerm,
PauliSum,
Expand Down Expand Up @@ -421,15 +421,21 @@ def test_exponentiate_identity():
generator = PauliTerm("I", 1, 1.0)
para_prog = exponential_map(generator)
prog = para_prog(1)
result_prog = Program().inst([X(0), PHASE(-1.0, 0), X(0), PHASE(-1.0, 0)])
result_prog = Program()
assert prog == result_prog

generator = PauliTerm("I", 10, 0.08)
para_prog = exponential_map(generator)
prog = para_prog(1)
result_prog = Program().inst([X(0), PHASE(-0.08, 0), X(0), PHASE(-0.08, 0)])
result_prog = Program()
assert prog == result_prog

pop = 2.1 * sI(0)
expprog = exponential_map(pop)
assert expprog(0.5) == Program()
pop.__dict__["_ops"][0] = "Y"
assert expprog(0.5) == Program()


def test_trotterize():
term_one = PauliTerm("X", 0, 1.0)
Expand Down
10 changes: 5 additions & 5 deletions pyquil/tests/test_paulis_with_placeholders.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import numpy as np
import pytest

from pyquil.gates import RX, RZ, CNOT, H, X, PHASE
from pyquil.gates import RX, RZ, CNOT, H
from pyquil.paulis import (
PauliTerm,
PauliSum,
Expand Down Expand Up @@ -398,14 +398,14 @@ def test_exponentiate_identity():
generator = PauliTerm("I", q[1], 1.0)
para_prog = exponential_map(generator)
prog = para_prog(1)
result_prog = Program().inst([X(q[0]), PHASE(-1.0, q[0]), X(q[0]), PHASE(-1.0, q[0])])
assert address_qubits(prog) == address_qubits(result_prog)
result_prog = Program()
assert prog == result_prog

generator = PauliTerm("I", q[10], 0.08)
para_prog = exponential_map(generator)
prog = para_prog(1)
result_prog = Program().inst([X(q[0]), PHASE(-0.08, q[0]), X(q[0]), PHASE(-0.08, q[0])])
assert address_qubits(prog) == address_qubits(result_prog)
result_prog = Program()
assert prog == result_prog


def test_trotterize():
Expand Down

0 comments on commit 4205213

Please sign in to comment.