From 6571d4dc7fb0aea8b2347899f09edb42281e12d6 Mon Sep 17 00:00:00 2001 From: John Lapeyre Date: Tue, 25 Feb 2020 10:21:12 -0800 Subject: [PATCH] Fix spurious PHASE and conditional in exponential_map * 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. --- CHANGELOG.md | 1 + pyquil/paulis.py | 25 +++++++++---------- pyquil/tests/test_paulis.py | 12 ++++++--- pyquil/tests/test_paulis_with_placeholders.py | 10 ++++---- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64f3a9e50..87dd1aec4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) --------------------------------------------------------------------------------------- diff --git a/pyquil/paulis.py b/pyquil/paulis.py index e2c868859..6d6c6c83a 100644 --- a/pyquil/paulis.py +++ b/pyquil/paulis.py @@ -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 @@ -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 diff --git a/pyquil/tests/test_paulis.py b/pyquil/tests/test_paulis.py index 2cc61dbd3..d35fb1bc0 100644 --- a/pyquil/tests/test_paulis.py +++ b/pyquil/tests/test_paulis.py @@ -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, @@ -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 = 0.0 * sX(0) + expprog = exponential_map(pop) + assert expprog(0.5) == Program() + pop.coefficient = 1.0 + assert expprog(0.5) == Program() + def test_trotterize(): term_one = PauliTerm("X", 0, 1.0) diff --git a/pyquil/tests/test_paulis_with_placeholders.py b/pyquil/tests/test_paulis_with_placeholders.py index 3449c8e1f..59edcaf1a 100644 --- a/pyquil/tests/test_paulis_with_placeholders.py +++ b/pyquil/tests/test_paulis_with_placeholders.py @@ -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, @@ -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():