Repository: rigetticomputing/pyquil (python)

Issue:
No designated zero element
Currently we have an `ID` element, which seems to me to be a useful idea, but we don't have a `ZERO` element, which means that initializing empty `PauliSums` ends up feeling a little hacky. I think having a `ZERO` element would make sense.

Pull request description:
Adding a designated zero element
Fixes #118 

Patch:
diff --git a/pyquil/paulis.py b/pyquil/paulis.py
index ee994cf..bbbe570 100644
--- a/pyquil/paulis.py
+++ b/pyquil/paulis.py
@@ -293,9 +293,13 @@ class PauliTerm(object):
 
 
 # For convenience, a shorthand for several operators.
-ID = PauliTerm("I", 0)
+ID = PauliTerm("I", 0, 1)
 """
-The identity Pauli operator on the 0th qubit.
+The identity Pauli Term.
+"""
+ZERO = PauliTerm("I", 0, 0)
+"""
+The zero Pauli Term.
 """
 sI = lambda q: PauliTerm("I", q)
 """
@@ -374,7 +378,7 @@ class PauliSum(object):
         if not isinstance(other, (PauliTerm, PauliSum)):
             raise TypeError("Can't compare PauliSum with object of type {}.".format(type(other)))
         elif isinstance(other, PauliTerm):
-            return self == PauliSum(other)
+            return self == PauliSum([other])
         elif len(self.terms) != len(other.terms):
             warnings.warn(UnequalLengthWarning("These PauliSums have a different number of terms."))
             return False


Test patch:
diff --git a/pyquil/tests/test_paulis.py b/pyquil/tests/test_paulis.py
index 6a59f75..2e83108 100644
--- a/pyquil/tests/test_paulis.py
+++ b/pyquil/tests/test_paulis.py
@@ -18,7 +18,7 @@
 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)
+                           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
 
@@ -526,6 +526,8 @@ def test_term_equality():
         sI(0) != 0
     assert sI(0) == sI(0)
     assert PauliTerm('X', 10, 1+1.j) == PauliTerm('X', 10, 1+1.j)
+    assert PauliTerm('X', 10, 1 + 1.j) + PauliTerm('X', 10, 1 + 1.j) != PauliTerm('X', 10, 1 + 1.j)
+    assert PauliTerm('X', 10, 1 + 1.j) != PauliTerm('X', 10, 1 + 1.j) + PauliTerm('X', 10, 1 + 1.j)
 
 
 def test_term_with_coeff():
@@ -549,6 +551,18 @@ def test_sum_equality():
         assert pauli_sum != 0
 
 
+def test_zero_term():
+    qubit_id = 0
+    coefficient = 10
+    ps = sI(qubit_id) + sX(qubit_id)
+    assert coefficient * ZERO == ZERO
+    assert ZERO * coefficient == ZERO
+    assert ZERO * ID == ZERO
+    assert ZERO + ID == ID
+    assert ZERO + ps == ps
+    assert ps + ZERO == ps
+    
+
 def test_from_list():
     terms_list = [("X", 0), ("Y", 1), ("Z", 5)]
     term = reduce(lambda x, y: x * y, [PauliTerm(*x) for x in terms_list])