diff --git a/stl/ast.py b/stl/ast.py index eddf9ed..e875df2 100644 --- a/stl/ast.py +++ b/stl/ast.py @@ -89,6 +89,10 @@ class AST(object): # TODO: this is hack to flatten the AST. Fix! return phi + def __hash__(self): + # TODO: compute hash based on contents + return hash(repr(self)) + class _Top(AST): __slots__ = () @@ -96,10 +100,6 @@ class _Top(AST): def __repr__(self): return "⊤" - def __hash__(self): - # TODO: compute hash based on contents - return hash(repr(self)) - def __invert__(self): return BOT @@ -110,10 +110,6 @@ class _Bot(AST): def __repr__(self): return "⊥" - def __hash__(self): - # TODO: compute hash based on contents - return hash(repr(self)) - def __invert__(self): return TOP diff --git a/stl/test_params.py b/stl/test_params.py index c6ca224..a29b097 100644 --- a/stl/test_params.py +++ b/stl/test_params.py @@ -1,4 +1,5 @@ import stl +from stl.hypothesis import SignalTemporalLogicStrategy import hypothesis.strategies as st from hypothesis import given @@ -12,3 +13,8 @@ def test_params1(a, b, c): phi2 = phi.set_params({'a?': a, 'b?': b, 'c?': c}) assert phi2.params == set() assert phi2 == stl.parse(f'G[{a}, {b}](x > {c})') + + +@given(SignalTemporalLogicStrategy) +def test_hash_stable(phi): + assert hash(phi) == hash(stl.parse(str(phi))) diff --git a/stl/test_utils.py b/stl/test_utils.py index 465a93e..fe09a5a 100644 --- a/stl/test_utils.py +++ b/stl/test_utils.py @@ -2,6 +2,7 @@ import stl from stl.hypothesis import SignalTemporalLogicStrategy from hypothesis import given +from pytest import raises CONTEXT = { @@ -23,6 +24,11 @@ def test_f_neg_or_canonical_form(phi): isinstance(x, (stl.ast.G, stl.ast.And)) for x in phi2.walk()) +def test_f_neg_or_canonical_form_not_implemented(): + with raises(NotImplementedError): + stl.utils.f_neg_or_canonical_form(stl.ast.AST()) + + def test_inline_context_rigid(): phi = stl.parse('G(AP1)') phi2 = phi.inline_context(CONTEXT)