Repository: rigetticomputing/pyquil (python)

Issue:
Function to exponentiate a PauliSum (analogous to exponential_map for PauliTerm)

Pull request description:
Resolves #263. exponentiate_pauli_sum, and test.

Patch:
diff --git a/pyquil/paulis.py b/pyquil/paulis.py
index 94f711f..c1efd58 100644
--- a/pyquil/paulis.py
+++ b/pyquil/paulis.py
@@ -696,6 +696,26 @@ def exponential_map(term):
     return exp_wrap
 
 
+def exponentiate_commuting_pauli_sum(pauli_sum):
+    """
+    Returns a function that maps all substituent PauliTerms and sums them into a program. NOTE: Use
+    this function with care. Substituent PauliTerms should commute.
+
+    :param PauliSum pauli_sum: PauliSum to exponentiate.
+    :returns: A function that parametrizes the exponential.
+    :rtype: function
+    """
+    if not isinstance(pauli_sum, PauliSum):
+        raise TypeError("Argument 'pauli_sum' must be a PauliSum.")
+
+    fns = [exponential_map(term) for term in pauli_sum]
+
+    def combined_exp_wrap(param):
+        return Program([f(param) for f in fns])
+
+    return combined_exp_wrap
+
+
 def _exponentiate_general_case(pauli_term, param):
     """
     Returns a Quil (Program()) object corresponding to the exponential of


Test patch:
diff --git a/pyquil/tests/test_paulis.py b/pyquil/tests/test_paulis.py
index 8e328ee..3d3e6d6 100644
--- a/pyquil/tests/test_paulis.py
+++ b/pyquil/tests/test_paulis.py
@@ -16,9 +16,10 @@
 ##############################################################################
 
 import pytest
-from pyquil.paulis import (PauliTerm, PauliSum, exponential_map, ID, UnequalLengthWarning,
-                           exponentiate, trotterize, is_zero, check_commutation,
-                           commuting_sets, term_with_coeff, sI, sX, sY, sZ, ZERO)
+from pyquil.paulis import (PauliTerm, PauliSum, exponential_map, exponentiate_commuting_pauli_sum,
+                           ID, UnequalLengthWarning, exponentiate, trotterize, is_zero,
+                           check_commutation, commuting_sets, term_with_coeff, sI, sX, sY,
+                           sZ, ZERO)
 from pyquil.quil import Program
 from pyquil.gates import RX, RZ, CNOT, H, X, PHASE
 
@@ -330,6 +331,13 @@ def test_exponentiate():
     assert prog == result_prog
 
 
+def test_exponentiate_commuting_pauli_sum():
+    pauli_sum = PauliSum([PauliTerm('Z', 0, 0.5), PauliTerm('Z', 1, 0.5)])
+    prog = Program().inst(RZ(1.)(0)).inst(RZ(1.)(1))
+    result_prog = exponentiate_commuting_pauli_sum(pauli_sum)(1.)
+    assert prog == result_prog
+
+
 def test_exponentiate_prog():
     ham = PauliTerm("Z", 0)
     result_prog = Program(RZ(2.0, 0))