Commit ed41bb02 authored by Kateřina Sloupová's avatar Kateřina Sloupová
Browse files

DFA equivalence and emptiness; NFA can epsilon

parent e7408f3b
Loading
Loading
Loading
Loading
Loading
+40 −13
Original line number Diff line number Diff line
from parser import Parser
from reg_automata import Character, State, DFA, NFA
from reg_automata import Character, State, DFA, NFA, NFAE, Eps
from reg_automata import Composition as comp
from reg_grammars import REG, Terminal, Nonterminal
from typing import Set, Dict, Tuple, Union
from copy import deepcopy


def make_dfa(states: Set[str], characters: Set[str],
@@ -66,6 +67,23 @@ def nfa_1():
    nfa = NFA({q0, q1, q2}, {a}, transition, q0, {q1, q2})
    return nfa

def nfa_e():
    q0 = State("q0")
    q1 = State("q1")
    q2 = State("q2")
    q3 = State("q3")
    q4 = State("q4")
    a = Character("a")
    b = Character("b")
    c = Character("c")
    d = Character("d")
    e = Eps()
    transition: Dict[Tuple[State, Union[Character, Eps]], Set[State]] = \
                {(q0, e): {q1}, (q1, a): {q0}, (q1, d): {q3}, (q1, e): {q2},
                 (q2, a): {q3}, (q3, e): {q4}, (q4, b): {q3}, (q4, c): {q2}}
    nfae = NFAE({q0, q1, q2, q3, q4}, {a, b, c, d}, transition, q0, {q2})
    return nfae

def main():
    dfa_1 = make_dfa({"q_0", "q_1"}, {"a"}, {("q_0", "a"): "q_1", ("q_1", "a"): "q_1"}, "q_0", {"q_1"})
    dfa_2 = make_dfa({"r_0", "r_1", "r_2"}, {"a", "b"}, {("r_0", "a"): "r_1", ("r_0", "b"): "r_1",
@@ -138,17 +156,18 @@ def main():
    print("DFA.eliminate_unreachable()")
    print("Add new state (also to transition) and eliminate unreachable states.")

    dfa_x = deepcopy(dfa_1)
    q_x = State("q_x")
    a = Terminal("a")
    dfa_1.states.add(q_x)
    dfa_1.final.add(q_x)
    dfa_1.transition[q_x, a] = q_x
    dfa_x.states.add(q_x)
    dfa_x.final.add(q_x)
    dfa_x.transition[q_x, a] = q_x
    print()
    print("DFA with new state:")
    print(parser.dfa_to_str(dfa_1, True))
    print(parser.dfa_to_str(dfa_x, True))
    print()
    print("DFA without unreachable states:")
    eliminated = dfa_1.eliminate_unreachable()
    eliminated = dfa_x.eliminate_unreachable()
    print(parser.dfa_to_str(eliminated, True))
    print()

@@ -158,7 +177,6 @@ def main():
    print()
    print(parser.dfa_to_str(dfa_3, True))


    print()
    print("Minimal DFA:")
    minimal = dfa_3.minimize()
@@ -191,6 +209,15 @@ def main():
    print(parser.nfa_to_str(regdfa, True))
    print()

    print("__________________________________")
    print("DFA.is_empty(), DFA.is_equivalent()")
    print("Emptiness with counterexample and equivalence \n"
          "of DFA through intersections with complements.")
    print()
    print("is dfa3 empty?", dfa_3.is_empty())
    print("dfa3 and canonical dfa3: ", dfa_3.is_equivalent(canonical), ", should be True")
    print()

    print("__________________________________")
    print("NFA.determinize()")
    print("Determinization of NFA to DFA:")
@@ -200,12 +227,12 @@ def main():
    print(parser.dfa_to_str(det, True))

    print("__________________________________")
    print("DFA.is_equivalent()")
    print("Equivalence of DFAs through intersections with complements.")
    print("NFAE.eliminate_epsilon()")
    print("Elimination of epsilon steps in NFA.")
    nfae = nfa_e()
    print(parser.nfa_to_str(nfae))
    print()

    print(dfa_3.is_equivalent(canonical), ", should be True")
    print()

    nfa_elim = nfae.eliminate_epsilon()
    print(parser.nfa_to_str(nfa_elim, True))

main()
 No newline at end of file

objects.py

0 → 100644
+587 −0

File added.

Preview size limit exceeded, changes collapsed.

+10 −5
Original line number Diff line number Diff line
from typing import List, Dict, Tuple, Optional
from typing import List, Dict, Tuple, Optional, Union
import re
from reg_automata import DFA, NFA
from reg_automata import DFA, NFA, NFAE, Eps
from reg_grammars import REG, Terminal


@@ -89,7 +89,7 @@ class Parser:
            return transition + "\n" + final


    def nfa_to_str(self, nfa: NFA, full : bool = False) -> str:
    def nfa_to_str(self, nfa: Union[NFA, NFAE], full : bool = False) -> str:

        # full - verbose description of DFA - only for development, dismiss later

@@ -108,7 +108,11 @@ class Parser:
        transition = ""
        for key, set_states in nfa.transition.items():
            state_1, terminal = key
            transition += "(" + state_1.name + "," + terminal.name + ")={"
            if isinstance(terminal, Eps):
                char = "epsilon"
            else:
                char = terminal.name
            transition += "(" + state_1.name + "," + char + ")={"
            for state in set_states:
                transition += state.name + ","
            transition = transition[:-1] + "}\n"
@@ -128,7 +132,8 @@ class Parser:
        else:
            return transition + "\n" + final

# TODO DFA/NFA to string are too similar
    def str_to_dfa(self, input: str):
        pass

# all: string <-> formal object
# reg
+117 −64

File changed.

Preview size limit exceeded, changes collapsed.

+2 −10

File changed.

Preview size limit exceeded, changes collapsed.