diff --git a/galgebra/dop.py b/galgebra/dop.py index 19f3226e..aa2f04d3 100644 --- a/galgebra/dop.py +++ b/galgebra/dop.py @@ -231,6 +231,15 @@ def __eq__(self, other): else: return NotImplemented + def __ne__(self, other): + result = self.__eq__(other) + if result is NotImplemented: + return result + return not result + + def __hash__(self): + return hash(self.terms) + def __add__(self, sdop): return Sdop.Add(self, sdop) @@ -312,6 +321,12 @@ def __eq__(self, A): return True return False + def __ne__(self, A): + return not self.__eq__(A) + + def __hash__(self): + return hash(tuple(sorted(self.pdiffs.items()))) + def __init__(self, __arg): """ The partial differential operator is a partial derivative with diff --git a/test/test_differential_ops.py b/test/test_differential_ops.py index 33a848fc..dcf2ea91 100644 --- a/test/test_differential_ops.py +++ b/test/test_differential_ops.py @@ -311,6 +311,32 @@ def test_multiply(self): with pytest.raises(TypeError): op(p, ex) + def test_hash_and_eq(self): + """Test Pdop/Sdop are hashable and support ne (issue 234).""" + x, y = symbols('x y', real=True) + p1 = Pdop(x) + p2 = Pdop(y) + p1b = Pdop(x) + p0 = Pdop({}) + + # Pdop is hashable + assert hash(p1) == hash(p1b) + assert {p1, p2, p1b} == {p1, p2} + + # ne works + assert p1 != p2 + assert not (p1 != p1b) + + # identity pdop + assert p0 == S.One + assert p0 != p1 + + # Sdop is hashable + s1 = Sdop([(x, p1)]) + s2 = Sdop([(y, p2)]) + assert hash(s1) is not None + assert {s1, s2} == {s1, s2} + def test_constructor_errors(self): # not a symbol or dict with pytest.raises(TypeError, match='dictionary or symbol is required'):