Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework the architecture #27

Draft
wants to merge 48 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
48 commits
Select commit Hold shift click to select a range
2e141f8
add finite automaton word generation
bygu4 Sep 28, 2024
5a7119e
add final path existance checks
bygu4 Sep 28, 2024
2ddf4ad
set up CI for all branches, minor style changes
bygu4 Sep 29, 2024
001d7a9
add tests for word generation, debug
bygu4 Sep 29, 2024
a97e69f
refactor
bygu4 Sep 29, 2024
660b8e9
make path check methods private, refactor, add type signatures
bygu4 Sep 30, 2024
7ca0408
import Tuple to debug
bygu4 Sep 30, 2024
d4e7a2f
add tests for transitions iteration
bygu4 Oct 2, 2024
76d5b75
update CI
bygu4 Oct 4, 2024
176a609
Merge pull request #3 from FormalLanguageConstrainedPathQuerying/fa_s…
bygu4 Oct 11, 2024
d72eff8
add max word length specification, refactor, add cyclic enfa test
bygu4 Oct 16, 2024
f49ce75
rewrite the generator without networkx
bygu4 Oct 16, 2024
5406e6f
use deque collection
bygu4 Oct 19, 2024
ed3e418
generalize _get_reachable_states, correct max length specification
bygu4 Oct 21, 2024
0fe3d88
avoid epsilon cycles, add tests with epsilon cycles, add tests with m…
bygu4 Oct 21, 2024
2ae69a3
minor style changes
bygu4 Oct 21, 2024
82202da
correct cycle checks, use BFS in _get_reachable_states
bygu4 Oct 22, 2024
7a0d27f
Merge from origin, update tests
bygu4 Oct 22, 2024
deed143
update tests for word generator
bygu4 Oct 22, 2024
bd3daba
add checks for any duplicates, add test for duplicate generation
bygu4 Oct 24, 2024
bffade7
Merge pull request #11 from FormalLanguageConstrainedPathQuerying/fa_…
bygu4 Oct 26, 2024
ebf7101
add type annotations for finite_automaton module, refactor
bygu4 Oct 13, 2024
9c0512b
rename _start_state, correct start_state property
bygu4 Oct 14, 2024
95a93fd
rework transition function
bygu4 Nov 11, 2024
7e54208
change input types to Hashable, add utils.py
bygu4 Nov 11, 2024
85a06d1
remove to_deterministic, refactor
bygu4 Nov 11, 2024
5ee276d
add type annotations for regex
bygu4 Oct 14, 2024
5fdb201
add annotations for python_regex
bygu4 Oct 15, 2024
422e4b5
refactor regex
bygu4 Nov 11, 2024
61acee7
refactor to_regex, remove regexable
bygu4 Nov 11, 2024
c1d8f46
make finite_automaton.copy generic, move regex to minimal dfa to Rege…
bygu4 Nov 12, 2024
f0b0030
reimplement regexable methods for epsilon_nfa
bygu4 Nov 12, 2024
fab3a37
refactor tests for fa to regex transitions
bygu4 Nov 12, 2024
f17cf85
correct union of enfas, refactor
bygu4 Nov 13, 2024
2a7aaac
correct partition, debug regex
bygu4 Nov 13, 2024
cf3ec20
debug, refactor tests
bygu4 Nov 13, 2024
fafd489
try to fix typing issue in python_regex
bygu4 Nov 13, 2024
e4bf660
correct pda intersection, add more tests for union, concatenation and…
bygu4 Nov 13, 2024
33d0895
add from_networkx abstract method to fa, use update instead of union …
bygu4 Nov 14, 2024
38880e7
add recursive automaton annotations
bygu4 Oct 22, 2024
30d00d9
minor style changes in automata
bygu4 Nov 15, 2024
72cd938
refactor PreviousTransitions
bygu4 Nov 16, 2024
ac97aec
handle cycles in get_states_leading_to_final, add more tests
bygu4 Nov 25, 2024
0c9930d
Merge pull request #13 from FormalLanguageConstrainedPathQuerying/fa_…
bygu4 Nov 28, 2024
b83c71a
Merge branch 'master' of github.com:FormalLanguageConstrainedPathQuer…
bygu4 Nov 28, 2024
7fcec6c
Merge pull request #12 from FormalLanguageConstrainedPathQuerying/rew…
bygu4 Nov 28, 2024
b5a0735
remove fastcore import, update pyright config
bygu4 Dec 9, 2024
94af59a
correct generic type naming, simplify _to_epsilon_nfa_internal method
bygu4 Dec 29, 2024
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
Prev Previous commit
Next Next commit
correct pda intersection, add more tests for union, concatenation and…
… kleene star
  • Loading branch information
bygu4 committed Nov 13, 2024
commit e4bf660b14264685ea23f3fb4c0e85420b27351d
74 changes: 70 additions & 4 deletions pyformlang/finite_automaton/tests/test_epsilon_nfa.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 87,7 @@ def test_deterministic(self):
assert not dfa.accepts([point])
assert not dfa.accepts([plus])

def test_union(self):
def test_union0(self):
""" Tests the union of two epsilon NFA """
enfa0 = get_enfa_example0()
enfa1 = get_enfa_example1()
Expand All @@ -101,7 101,25 @@ def test_union(self):
assert not enfa.accepts([symb_a])
assert not enfa.accepts([])

def test_concatenate(self):
def test_union1(self):
"""
Tests the union of three ENFAs.
Union is (a*b)|(ab )|c
"""
enfa0 = get_enfa_example0()
enfa1 = get_enfa_example1()
enfa2 = get_enfa_example2()
enfa = enfa0 | enfa2
enfa |= enfa1
accepted_words = list(enfa.get_accepted_words(3))
assert ["b"] in accepted_words
assert ["a", "b"] in accepted_words
assert ["a", "a", "b"] in accepted_words
assert ["a", "b", "b"] in accepted_words
assert ["c"] in accepted_words
assert len(accepted_words) == 5

def test_concatenate0(self):
""" Tests the concatenation of two epsilon NFA """
enfa0 = get_enfa_example0()
enfa1 = get_enfa_example1()
Expand All @@ -116,7 134,23 @@ def test_concatenate(self):
assert not enfa.accepts([symb_b])
assert not enfa.accepts([])

def test_kleene(self):
def test_concatenate1(self):
"""
Tests the concatenation of three ENFAs.
Concatenation is a*bc((ab )|c)
"""
enfa0 = get_enfa_example0()
enfa1 = get_enfa_example1()
enfa2 = get_enfa_example2()
enfa = enfa0 enfa1
enfa = enfa2
accepted_words = list(enfa.get_accepted_words(4))
assert ["b", "c", "c"] in accepted_words
assert ["a", "b", "c", "c"] in accepted_words
assert ["b", "c", "a", "b"] in accepted_words
assert len(accepted_words) == 3

def test_kleene0(self):
""" Tests the kleene star of an epsilon NFA """
enfa0 = get_enfa_example0()
symb_a = Symbol("a")
Expand All @@ -130,6 164,23 @@ def test_kleene(self):
assert not enfa.accepts([symb_a])
assert not enfa.accepts([symb_a, symb_b, symb_a])

def test_kleene1(self):
"""
Tests the kleene star of an ENFA.
Expression is ((ab )|c)*
"""
enfa = get_enfa_example2()
enfa = enfa.kleene_star()
accepted_words = list(enfa.get_accepted_words(3))
assert [] in accepted_words
assert ["a", "b"] in accepted_words
assert ["a", "b", "b"] in accepted_words
assert ["a", "b", "c"] in accepted_words
assert ["c", "a", "b"] in accepted_words
for i in range(3):
assert ["c"] * (i 1) in accepted_words
assert len(accepted_words) == 8

def test_complement(self):
""" Tests the complement operation """
enfa = EpsilonNFA()
Expand Down Expand Up @@ -544,7 595,7 @@ def get_enfa_example0():


def get_enfa_example1():
""" Gives and example ENFA
""" Gives an example ENFA
Accepts c
"""
enfa1 = EpsilonNFA()
Expand All @@ -557,6 608,21 @@ def get_enfa_example1():
return enfa1


def get_enfa_example2():
""" Gives an example ENFA
Accepts (ab )|c
"""
enfa = EpsilonNFA(start_states={0, 3},
final_states={2, 4})
enfa.add_transitions([
(0, "a", 1),
(1, "b", 2),
(2, "b", 2),
(3, "c", 4),
])
return enfa


def get_enfa_example0_bis():
""" A non minimal NFA, equivalent to example0 """
enfa0 = EpsilonNFA()
Expand Down
44 changes: 20 additions & 24 deletions pyformlang/pda/pda.py
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 467,11 @@ def intersection(self, other: DeterministicFiniteAutomaton) -> "PDA":
When intersecting with something else than a regex or a finite
automaton
"""
start_state_other = other.start_states
if len(start_state_other) == 0:
start_state_other = other.start_state
if not start_state_other:
return PDA()
pda_state_converter = _PDAStateConverter(self._states, other.states)
start_state_other = list(start_state_other)[0]
final_state_other = other.final_states
final_states_other = other.final_states
start = pda_state_converter.to_pda_combined_state(self._start_state,
start_state_other)
pda = PDA(start_state=start,
Expand All @@ -484,40 483,37 @@ def intersection(self, other: DeterministicFiniteAutomaton) -> "PDA":
while to_process:
state_in, state_dfa = to_process.pop()
if (state_in in self._final_states and state_dfa in
final_state_other):
final_states_other):
pda.add_final_state(
pda_state_converter.to_pda_combined_state(state_in,
state_dfa))
for symbol in symbols:
if symbol == Epsilon():
symbol_dfa = finite_automaton.Epsilon()
next_state_dfa = state_dfa
else:
symbol_dfa = finite_automaton.Symbol(symbol.value)
if symbol == Epsilon():
next_states_dfa = [state_dfa]
else:
next_states_dfa = other(state_dfa, symbol_dfa)
if len(next_states_dfa) == 0:
next_state_dfa = other.get_next_state(state_dfa, symbol_dfa)
if not next_state_dfa:
continue
for stack_symbol in self._stack_alphabet:
next_states_self = self._transition_function(state_in,
symbol,
stack_symbol)
for next_state, next_stack in next_states_self:
for next_state_dfa in next_states_dfa:
pda.add_transition(
pda_state_converter.to_pda_combined_state(
state_in,
state_dfa),
symbol,
stack_symbol,
pda_state_converter.to_pda_combined_state(
next_state,
next_state_dfa),
next_stack)
if (next_state, next_state_dfa) not in processed:
to_process.append((next_state, next_state_dfa))
processed.add((next_state, next_state_dfa))
pda.add_transition(
pda_state_converter.to_pda_combined_state(
state_in,
state_dfa),
symbol,
stack_symbol,
pda_state_converter.to_pda_combined_state(
next_state,
next_state_dfa),
next_stack)
if (next_state, next_state_dfa) not in processed:
to_process.append((next_state, next_state_dfa))
processed.add((next_state, next_state_dfa))
return pda

def __and__(self, other: DeterministicFiniteAutomaton) -> "PDA":
Expand Down