Ejemplo n.º 1
0
def test_set_new_transtable():

    alphabet = ["a", "b"]
    states = ["1", "2"]

    table = TransitionTable(alphabet, states)
    table.add_transition("a", "2", "2")
    table.add_transition("b", "2", "2")
    table.add_transition("a", "1", "2")
    table.add_transition("b", "1", "1")

    dfa = DFA(table)

    # invalid table
    try:
        dfa.trans_table = {}
    except ValueError:
        pass

    # new table
    new_table = TransitionTable(alphabet, states)
    new_table.add_transition("b", "2", "2")
    new_table.add_transition("a", "1", "2")
    new_table.add_transition("b", "1", "1")

    dfa.trans_table = new_table
Ejemplo n.º 2
0
def test_set_new_transtable():

    alphabet = ["a", "b"]
    states = ["1", "2"]

    table = TransitionTable(alphabet, states)
    table.add_transition("a", "2", "2")
    table.add_transition("b", "2", "2")
    table.add_transition("a", "1", "2")
    table.add_transition("b", "1", "1")

    dfa = DFA(table)

    # invalid table
    try:
        dfa.trans_table = {}
    except ValueError:
        pass

    # new table
    new_table = TransitionTable(alphabet, states)
    new_table.add_transition("b", "2", "2")
    new_table.add_transition("a", "1", "2")
    new_table.add_transition("b", "1", "1")

    dfa.trans_table = new_table
Ejemplo n.º 3
0
def test_consume():

    alphabet = ["a", "b"]
    states = ["1", "2"]

    table = TransitionTable(alphabet, states)
    table.add_transition("b", "2", "2")
    table.add_transition("a", "1", "2")
    table.add_transition("b", "1", "1")

    dfa = DFA(table)

    # accepted string
    accepted = dfa.consume("ba")
    assert accepted, "'ba' is expected to be accepted."

    accepted = dfa.consume("babbb")
    assert accepted, "'babbb' is expected to be accepted."

    # not acceptable string
    accepted = dfa.consume("b")
    assert not accepted, "'b' is expected not to be accepted."

    accepted = dfa.consume("bbb")
    assert not accepted, "'bbb' is expected not to be accepted."

    # dead state
    accepted = dfa.consume("bbaba")
    assert not accepted, "'bbaba' is expected not to be accepted."

    # invalid transition
    accepted = dfa.consume("babbbc")
    assert not accepted, "'bac' is expected not to be accepted."
Ejemplo n.º 4
0
    def nfa_to_dfa(self):
        try:
            self.alphabet.remove('ε')
        except:
            pass

        self.new_ss = state({s.id for s in self.start_states})
        temp_op = {key: set() for key in self.alphabet + ['ε']}
        for ss in self.start_states:
            for k, v in ss.outpaths.items():
                set_v = set(v)
                temp_op[k] = temp_op[k].union(set_v)
        self.new_ss.outpaths = {k: list(v) for k, v in temp_op.items()}
        self.new_ss.made_of = set(self.start_states)
        self.states.append(self.new_ss)

        self.e_transitions()
        if 'ε' in self.new_ss.outpaths:
            del self.new_ss.outpaths['ε']

        existing_states = [self.new_ss.made_of]
        new_states = [self.new_ss]
        dfa_states = [self.new_ss]

        while len(new_states) > 0:
            next_round = []
            for es in new_states:
                new_dict = {key: set() for key in self.alphabet}
                for sub_state in es.made_of:
                    for char, states in sub_state.ep_outpaths.items():
                        new_dict[char] = new_dict[char].union(states)
                for char, states in new_dict.items():
                    if states not in existing_states:
                        id = set([s.id for s in states])
                        if id == set():
                            id = '∅'
                        new_state = state(id)
                        new_state.made_of = states
                        es.outpaths[char] = new_state
                        dfa_states.append(new_state)
                        existing_states.append(states)
                        next_round.append(new_state)
                    else:
                        for x in dfa_states:
                            if x.made_of == states:
                                es.outpaths[char] = x
                                break
            new_states = next_round

        self.my_dfa = DFA(dfa_states)
        self.my_dfa.alphabet = self.alphabet
        self.my_dfa.start_state = self.new_ss

        acc_ids = {st.id for st in self.accept_states}
        for st in self.my_dfa.states:
            for s in st.made_of:
                if s.id in acc_ids:
                    self.my_dfa.accept_states.append(st)
                    break
Ejemplo n.º 5
0
def test_consume():

    alphabet = ["a", "b"]
    states = ["1", "2"]

    table = TransitionTable(alphabet, states)
    table.add_transition("b", "2", "2")
    table.add_transition("a", "1", "2")
    table.add_transition("b", "1", "1")

    dfa = DFA(table)

    # accepted string
    accepted = dfa.consume("ba")
    assert accepted, "'ba' is expected to be accepted."

    accepted = dfa.consume("babbb")
    assert accepted, "'babbb' is expected to be accepted."

    # not acceptable string
    accepted = dfa.consume("b")
    assert not accepted, "'b' is expected not to be accepted."

    accepted = dfa.consume("bbb")
    assert not accepted, "'bbb' is expected not to be accepted."

    # dead state
    accepted = dfa.consume("bbaba")
    assert not accepted, "'bbaba' is expected not to be accepted."

    # invalid transition
    accepted = dfa.consume("babbbc")
    assert not accepted, "'bac' is expected not to be accepted."
Ejemplo n.º 6
0
 def test_dfa_match_bad(self):
     tr = {(0, 15): 1,
           (0, 22): 2,
           (1, 17): 3,
           (2, 17): 3,
           (2, 22): 4,
           (3, 22): 4,
           (4, 233): 4
           }
     fs = {1: {'regex1'},
           4: {'regex2'}
           }
     dfa = DFA(5, tr, 0, fs)
     seq = [2]
     self.assertEqual(dfa.match(seq), set(), "Matching the empty sequence should stay in the start state which is not final in this example")
     
     tr = {(0, 15): 1,
           (0, 22): 2,
           (1, 17): 3,
           (2, 17): 3,
           (2, 22): 4,
           (3, 22): 4,
           (4, 233): 4
           }
     fs = {1: {'regex1'},
           4: {'regex2'}
           }
     dfa = DFA(5, tr, 0, fs)
     seq = [22, 22, 233, 2]
     self.assertEqual(dfa.match(seq), set(), "If a transition is undefined, it must return set()")
Ejemplo n.º 7
0
    def test_dfa_match_good1(self):
        tr = {(0, 15): 1,
              (0, 22): 2,
              (1, 17): 3,
              (2, 17): 3,
              (2, 22): 4,
              (3, 22): 4,
              (4, 233): 4
              }
        fs = {1: {'regex1'},
              4: {'regex2'}
              }
        dfa = DFA(5, tr, 0, fs)
        seq = [15]
        self.assertEqual(dfa.match(seq), {'regex1'}, "In this example, the sequence [15] leads into final state 1 that should return regex1 as label")

        tr = {(0, 15): 1,
              (0, 22): 2,
              (1, 17): 3,
              (2, 17): 3,
              (2, 22): 4,
              (3, 22): 4,
              (4, 233): 4
              }
        fs = {1: {'regex1'},
              4: {'regex2'}
              }
        dfa = DFA(5, tr, 0, fs)
        seq = [15, 17, 22, 233]
        self.assertEqual(dfa.match(seq), {'regex2'}, "In this example, the sequence [15, 17, 22, 233] leads into final state 4 that should return regex2 as label")
Ejemplo n.º 8
0
 def setup(self):
     # DFA which matches all binary strings ending in an odd number of '1's
     self.dfa = DFA(**{
         'states': {'q0', 'q1', 'q2'},
         'symbols': {'0', '1'},
         'transitions': {
             'q0': {'0': 'q0', '1': 'q1'},
             'q1': {'0': 'q0', '1': 'q2'},
             'q2': {'0': 'q2', '1': 'q1'}
         },
         'initial_state': 'q0',
         'final_states': {'q1'}
     })
Ejemplo n.º 9
0
def test2():
    #Example 13.1 from Automata & Computability
    print('Test 2')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s0.outpaths = {'a': s1, 'b': s3}
    s1.outpaths = {'a': s2, 'b': s2}
    s2.outpaths = {'a': s2, 'b': s2}
    s3.outpaths = {'a': s2, 'b': s2}
    d = DFA([s0,s1,s2,s3])
    d.start_state = s0
    d.accept_states = [s1, s3]
    d.alphabet = ['a', 'b']
    d.minimize()
    d.print_dfa(True)

    """
Ejemplo n.º 10
0
    def subset_construction(self):
        # based on:
        # Subset Construction presented by Ullman (Automata course)
        # extended with closure operation to work with epsilon transitions
        states = 1
        numeric_state = dict()
        closure = self.epsilon_closure()
        start = frozenset(closure[self.start])
        numeric_state[start] = states - 1
        finals = dict()

        # empty transitions dictionary
        tr = dict()

        queue = collections.deque([start])

        # if one of the subset states in the DFA start state is already final
        fin = start & self.final.keys()
        if fin:
            # start state is always id 0
            finals[0] = {label for q in fin for label in self.final[q]}

        while queue:
            # print(len(queue))
            curr_state = queue.popleft()
            for (a, state_set) in self.successors(curr_state).items():
                # for a in range(256):
                # next_state = self.next(curr_state, a)
                next_state = frozenset(state_set)

                if next_state:
                    # the state exists
                    if next_state not in numeric_state.keys():
                        states += 1
                        numeric_state[next_state] = states - 1
                        # add into queue so it gets resolved in next round
                        queue.append(next_state)

                    tr[numeric_state[curr_state],
                       a] = numeric_state[next_state]
                    fin = next_state & self.final.keys()
                    if fin:
                        finals[numeric_state[next_state]] = {
                            label
                            for q in fin for label in self.final[q]
                        }
        # print("State Subsets", numeric_state)
        return DFA(states, tr, 0, finals)
Ejemplo n.º 11
0
def test1():
    #from https://www.gatevidyalay.com/minimization-of-dfa-minimize-dfa-example/
    print('Test 1')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s4 = state(4)
    s0.outpaths = {'a': s1, 'b': s2}
    s1.outpaths = {'a': s1, 'b': s3}
    s2.outpaths = {'a': s1, 'b': s2}
    s3.outpaths = {'a': s1, 'b': s4}
    s4.outpaths = {'a': s1, 'b': s2}
    d = DFA([s0,s1,s2,s3,s4])
    d.start_state = s1
    d.accept_states = [s4]
    d.alphabet = ['a', 'b']
    d.minimize()
    d.print_dfa(True)

    """
Ejemplo n.º 12
0
def test1():
    #1a in HW3 in Automata & Computability
    print('Test 1')
    s0 = state(0)
    s1 = state(1)
    s0.outpaths = {'a': s1, 'b': s0}
    s1.outpaths = {'a': s0, 'b': s1}
    d = DFA([s0, s1])
    d.start_state = s0
    d.accept_states = [s0]
    d.alphabet = ['a', 'b']
    print(d.all_regex(False) + '\n')
Ejemplo n.º 13
0
def test4():
    #Example 13.2 from Automata & Computability
    print('Test 4')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s4 = state(4)
    s5 = state(5)
    s0.outpaths = {'a': s1, 'b': s2}
    s1.outpaths = {'a': s3, 'b': s4}
    s2.outpaths = {'a': s4, 'b': s3}
    s3.outpaths = {'a': s5, 'b': s5}
    s4.outpaths = {'a': s5, 'b': s5}
    s5.outpaths = {'a': s5, 'b': s5}
    d = DFA([s0,s1,s2,s3,s4,s5])
    d.start_state = s0
    d.accept_states = [s1, s2, s5]
    d.alphabet = ['a', 'b']
    d.minimize()
    d.print_dfa(True)

    """
Ejemplo n.º 14
0
def test3():
    #from https://www.geeksforgeeks.org/minimization-of-dfa/
    print('Test 3')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s4 = state(4)
    s5 = state(5)
    s0.outpaths = {'0': s3, '1': s1}
    s1.outpaths = {'0': s2, '1': s5}
    s2.outpaths = {'0': s2, '1': s5}
    s3.outpaths = {'0': s0, '1': s4}
    s4.outpaths = {'0': s2, '1': s5}
    s5.outpaths = {'0': s5, '1': s5}
    d = DFA([s0,s1,s2,s3,s4,s5])
    d.start_state = s0
    d.accept_states = [s1, s2, s4]
    d.alphabet = ['0', '1']
    d.minimize()
    d.print_dfa(True)

    """
Ejemplo n.º 15
0
def test5():
    #accepts any variant of a(ba)*a
    print('Test 5')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s0.outpaths = {'a': s1}
    s1.outpaths = {'a': s2, 'b': s0}
    d = DFA([s0, s1, s2])
    d.start_state = s0
    d.accept_states = [s2]
    d.alphabet = ['a', 'b']
    print(d.all_regex(False))
Ejemplo n.º 16
0
def test3():
    #1d in HW3 in Automata & Computability
    print('Test 3')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s0.outpaths = {'a': s2, 'b': s1}
    s1.outpaths = {'a': s3, 'b': s0}
    s2.outpaths = {'a': s0, 'b': s3}
    s3.outpaths = {'a': s1, 'b': s2}
    d = DFA([s0, s1, s2, s3])
    d.start_state = s0
    d.accept_states = [s1]
    d.alphabet = ['a', 'b']
    print(d.all_regex() + '\n')
Ejemplo n.º 17
0
def test4():
    #pg 17 Example 3.2 from Automata & Computability
    #accepts strings w/ 3 consecutive a's
    print('Test 4')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s0.outpaths = {'a': s1, 'b': s0}
    s1.outpaths = {'a': s2, 'b': s0}
    s2.outpaths = {'a': s3, 'b': s0}
    s3.outpaths = {'a': s3, 'b': s3}
    d = DFA([s0, s1, s2, s3])
    d.start_state = s0
    d.accept_states = [s3]
    d.alphabet = ['a', 'b']
    print(d.all_regex() + '\n')
Ejemplo n.º 18
0
 def test_from_nfa_simple(self):
     """should properly convert a simple NFA to a DFA"""
     nfa = NFA(**{
         'states': {'q0', 'q1', 'q2'},
         'symbols': {'0', '1'},
         'transitions': {
             'q0': {'0': {'q0', 'q1'}},
             'q1': {'1': {'q2'}},
             'q2': {}
         },
         'initial_state': 'q0',
         'final_states': {'q2'}
     })
     dfa = DFA.from_nfa(nfa)
     nose.assert_equal(dfa.states, {'{}', '{q0}', '{q0q1}', '{q2}'})
     nose.assert_equal(dfa.symbols, {'0', '1'})
     nose.assert_equal(dfa.transitions, {
         '{}': {'0': '{}', '1': '{}'},
         '{q0}': {'0': '{q0q1}', '1': '{}'},
         '{q0q1}': {'0': '{q0q1}', '1': '{q2}'},
         '{q2}': {'0': '{}', '1': '{}'}
     })
     nose.assert_equal(dfa.initial_state, '{q0}')
     nose.assert_equal(dfa.final_states, {'{q2}'})
Ejemplo n.º 19
0
 def test_dfa_match_empty(self):
     tr = {(0, 15): 1,
           (0, 22): 2,
           (1, 17): 3,
           (2, 17): 3,
           (2, 22): 4,
           (3, 22): 4,
           (4, 233): 4
           }
     fs = {1: {'regex1'},
           4: {'regex2'}
           }
     dfa = DFA(5, tr, 0, fs)
     seq = []
     self.assertEqual(dfa.match(seq), set(), "Matching the empty sequence should stay in the start state which is not final")
     tr = {(0, 15): 0}
     fs = {0: {'regex1'}}
     dfa = DFA(1, tr, 0, fs)
     self.assertEqual(dfa.match([]), {"regex1"}, "In this example, the start state is accepting, so the empty sequence should return the correct label")
Ejemplo n.º 20
0
def test6():
    #Example 13.2 from Automata & Computability
    #accepts {a,b} and any strings with 3+ characters
    print('Test 6')
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s4 = state(4)
    s5 = state(5)
    s0.outpaths = {'a': s1, 'b': s2}
    s1.outpaths = {'a': s3, 'b': s4}
    s2.outpaths = {'a': s4, 'b': s3}
    s3.outpaths = {'a': s5, 'b': s5}
    s4.outpaths = {'a': s5, 'b': s5}
    s5.outpaths = {'a': s5, 'b': s5}
    d = DFA([s0, s1, s2, s3, s4, s5])
    d.start_state = s0
    d.accept_states = [s1, s2, s5]
    d.alphabet = ['a', 'b']
    print(d.all_regex())
Ejemplo n.º 21
0
 def create_fa(self, expression, alphabet):
     new_FA = DFA()
     new_FA.set_name(str(expression))
     self.FA_list.append(new_FA)
     self.add_tab(expression, ['FA', alphabet])
Ejemplo n.º 22
0
class TestDFA():

    def setup(self):
        # DFA which matches all binary strings ending in an odd number of '1's
        self.dfa = DFA(**{
            'states': {'q0', 'q1', 'q2'},
            'symbols': {'0', '1'},
            'transitions': {
                'q0': {'0': 'q0', '1': 'q1'},
                'q1': {'0': 'q0', '1': 'q2'},
                'q2': {'0': 'q2', '1': 'q1'}
            },
            'initial_state': 'q0',
            'final_states': {'q1'}
        })

    def test_init_json(self):
        """should copy given JSON object into new DFA"""
        with open('tests/files/dfa.json', 'r') as dfa_file:
            dfa_json = json.load(dfa_file)
        new_dfa = DFA(**dfa_json)
        nose.assert_equal(new_dfa.states, set(dfa_json['states']))
        nose.assert_is_not(new_dfa.states, dfa_json['states'])
        nose.assert_equal(new_dfa.symbols, set(dfa_json['symbols']))
        nose.assert_is_not(new_dfa.symbols, dfa_json['symbols'])
        nose.assert_equal(new_dfa.transitions, dict(dfa_json['transitions']))
        nose.assert_is_not(new_dfa.transitions, dfa_json['transitions'])
        nose.assert_equal(new_dfa.initial_state, dfa_json['initial_state'])
        nose.assert_equal(new_dfa.final_states, set(dfa_json['final_states']))
        nose.assert_is_not(new_dfa.final_states, dfa_json['final_states'])

    def test_validate_automaton_missing_state(self):
        """should raise error if a state has no transitions defined"""
        with nose.assert_raises(automaton.MissingStateError):
            del self.dfa.transitions['q1']
            self.dfa.validate_automaton()

    def test_validate_automaton_missing_symbol(self):
        """should raise error if a symbol transition is missing"""
        with nose.assert_raises(automaton.MissingSymbolError):
            del self.dfa.transitions['q1']['1']
            self.dfa.validate_automaton()

    def test_validate_automaton_invalid_symbol(self):
        """should raise error if a transition references an invalid symbol"""
        with nose.assert_raises(automaton.InvalidSymbolError):
            self.dfa.transitions['q1']['2'] = 'q2'
            self.dfa.validate_automaton()

    def test_validate_automaton_invalid_state(self):
        """should raise error if a transition references an invalid state"""
        with nose.assert_raises(automaton.InvalidStateError):
            self.dfa.transitions['q1']['1'] = 'q3'
            self.dfa.validate_automaton()

    def test_validate_automaton_invalid_initial_state(self):
        """should raise error if the initial state is invalid"""
        with nose.assert_raises(automaton.InvalidStateError):
            self.dfa.initial_state = 'q3'
            self.dfa.validate_automaton()

    def test_validate_automaton_invalid_final_state(self):
        """should raise error if the final state is invalid"""
        with nose.assert_raises(automaton.InvalidStateError):
            self.dfa.final_states = {'q3'}
            self.dfa.validate_automaton()

    def test_validate_input_valid(self):
        """should return correct stop state when valid DFA input is given"""
        nose.assert_equal(self.dfa.validate_input('0111'), 'q1')

    def test_validate_input_invalid_symbol(self):
        """should raise error if an invalid symbol is read"""
        with nose.assert_raises(automaton.InvalidSymbolError):
            self.dfa.validate_input('01112')

    def test_validate_input_nonfinal_state(self):
        """should raise error if the stop state is not a final state"""
        with nose.assert_raises(automaton.FinalStateError):
            self.dfa.validate_input('011')

    def test_from_nfa_simple(self):
        """should properly convert a simple NFA to a DFA"""
        nfa = NFA(**{
            'states': {'q0', 'q1', 'q2'},
            'symbols': {'0', '1'},
            'transitions': {
                'q0': {'0': {'q0', 'q1'}},
                'q1': {'1': {'q2'}},
                'q2': {}
            },
            'initial_state': 'q0',
            'final_states': {'q2'}
        })
        dfa = DFA.from_nfa(nfa)
        nose.assert_equal(dfa.states, {'{}', '{q0}', '{q0q1}', '{q2}'})
        nose.assert_equal(dfa.symbols, {'0', '1'})
        nose.assert_equal(dfa.transitions, {
            '{}': {'0': '{}', '1': '{}'},
            '{q0}': {'0': '{q0q1}', '1': '{}'},
            '{q0q1}': {'0': '{q0q1}', '1': '{q2}'},
            '{q2}': {'0': '{}', '1': '{}'}
        })
        nose.assert_equal(dfa.initial_state, '{q0}')
        nose.assert_equal(dfa.final_states, {'{q2}'})
Ejemplo n.º 23
0
	def create_fa(self, expression, alphabet):
		automata = DFA()
		automata.set_name(str(expression))
		self.FA_list.append(automata)
		self.add_tab(expression, ['FA', alphabet])