From 406f63bef7102290297286bea802016df814d52e 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 | 22 +++++++++---------- pyquil/tests/test_paulis.py | 12 +++++++--- pyquil/tests/test_paulis_with_placeholders.py | 8 +++---- 4 files changed, 25 insertions(+), 18 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..3c4780d49 100644 --- a/pyquil/paulis.py +++ b/pyquil/paulis.py @@ -923,18 +923,18 @@ def exponential_map(term: PauliTerm) -> Callable[[float], Program]: 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..cad11127a 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 = 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) diff --git a/pyquil/tests/test_paulis_with_placeholders.py b/pyquil/tests/test_paulis_with_placeholders.py index 3449c8e1f..ab25505db 100644 --- a/pyquil/tests/test_paulis_with_placeholders.py +++ b/pyquil/tests/test_paulis_with_placeholders.py @@ -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():