Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions bindings/python/libmata/nfa/nfa.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class Transition:
:param State target: target state
"""
def __eq__(self, other: Self) -> bool: ...
def __neq__(self, other: Self) -> bool: ...
def __hash__(self) -> int: ...

class SymbolPost:
"""Wrapper over pair of symbol and states for transitions"""
Expand All @@ -73,7 +73,6 @@ class SymbolPost:
def __le__(self, other: Self) -> bool: ...
def __ge__(self, other: Self) -> bool: ...
def __eq__(self, other: Self) -> bool: ...
def __neq__(self, other: Self) -> bool: ...

class Delta:
"""Wrapper over the transition relation (`Delta`) of an automaton, allowing operations on transitions similar
Expand Down
7 changes: 3 additions & 4 deletions bindings/python/libmata/nfa/nfa.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ cdef class Transition:
def __eq__(self, Transition other):
return dereference(self.thisptr) == dereference(other.thisptr)

def __neq__(self, Transition other):
return dereference(self.thisptr) != dereference(other.thisptr)
def __hash__(self):
return hash((self.source, self.symbol, self.target))

def __str__(self):
return f"{self.thisptr.source}-[{self.thisptr.symbol}]\u2192{self.thisptr.target}"
Expand Down Expand Up @@ -173,8 +173,7 @@ cdef class SymbolPost:
def __eq__(self, SymbolPost other):
return self.symbol == other.symbol and self.targets == other.targets

def __neq__(self, SymbolPost other):
return self.symbol != other.symbol or self.targets != other.targets
# `SymbolPost` stays unhashable: its `symbol`/`targets` setters make instances mutable.

def __str__(self):
trans = "{" + ",".join(map(str, self.targets)) + "}"
Expand Down
21 changes: 21 additions & 0 deletions bindings/python/tests/test_nfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -1304,3 +1304,24 @@ def test_get_words_lazy_without_generator_support():
nfa.add_transition(1, 2, 2)
with pytest.raises(RuntimeError):
next(iter(nfa.get_words_lazy(5)))


def test_transition_hashing():
"""Tests that transitions can be used in sets and as dictionary keys."""
first = mata_nfa.Transition(1, 2, 3)
second = mata_nfa.Transition(1, 2, 3)
other = mata_nfa.Transition(1, 2, 4)

assert first == second
assert hash(first) == hash(second)
assert first != other
# Spelled out rather than as `first == second`: this checks the `__ne__` derived from `__eq__`.
assert (first != second) is False

assert len({first, second, other}) == 2

mapping = {first: "a", other: "b"}
mapping[second] = "c"
assert mapping[first] == "c"
assert mapping[other] == "b"
assert len(mapping) == 2
Loading