Пример #1
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
Пример #2
0
def test1():
    s0 = state(0)
    s1 = state(1)
    s0.outpaths = {'b': [s0, s1]}
    s1.outpaths = {'a': [s1], 'b': [s0]}
    n = NFA([s0, s1])
    n.start_states = [s0]
    n.accept_states = [s1]
    n.alphabet = ['a', 'b']
    n.nfa_to_dfa()
    n.my_dfa.print_dfa()
    """
Пример #3
0
def test1():
    #strings in the language {a^n b^n | n >= 1}
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s0.outpaths = {
        ('a', 'A'): {(s0, 'AA')},
        ('a', '$'): {(s0, 'A$')},
        ('b', 'A'): {(s1, 'ε')}
    }
    s1.outpaths = {('b', 'A'): {(s1, 'ε')}, ('ε', '$'): {(s2, 'ε')}}
    p = PDA({s0, s1, s2})
    p.input_alphabet = {'a', 'b'}
    p.stack_symbols = {'$', 'A', 'B'}
    p.start_state = s0
    p.accept_states = {s2}
    p.to_cfg()
    p.my_cfg.print_converted_cfg()
Пример #4
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)

    """
Пример #5
0
    def make_nfa_part(self, part, num):
        if '*' not in part:
            states = [state(i) for i in range(num, num + len(part) + 1)]
            for i in range(len(states) - 1):
                states[i].outpaths[part[i]] = [states[i + 1]]
            return states, num + len(part) + 1
        else:
            starred_letters_index = set()
            for i in range(len(part)):
                if part[i] == '*':
                    starred_letters_index.add(i - 1)

            states = [state(num)]
            num += 1
            i = 0
            while i < len(part):
                if i not in starred_letters_index:
                    new_state = state(num)
                    if part[i] in states[-1].outpaths:
                        states[-1].outpaths.append(new_state)
                    else:
                        states[-1].outpaths[part[i]] = [new_state]
                    states.append(new_state)
                    num += 1
                    i += 1
                else:
                    if part[i] in states[-1].outpaths:
                        states[-1].outpaths.append(states[-1])
                    else:
                        states[-1].outpaths[part[i]] = [states[-1]]
                    if i < len(part) - 2 and i + 2 in starred_letters_index:
                        new_state = state(num)
                        if 'ε' in states[
                                -1].outpaths:  #check not necessary unless 'ε' in alphabet?
                            states[-1].outpaths['ε'].append(new_state)
                        else:
                            states[-1].outpaths['ε'] = [new_state]
                        states.append(new_state)
                        num += 1
                    i += 2
            return states, num
Пример #6
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)

    """
Пример #7
0
def test2():
    #strings in the language {a^m b^m c^n d^n | m,n >= 1}
    #https://scanftree.com/automata/dpda-for-a-to-power-n-b-to-power-n-c-to-power-m-d-to-power-m
    s0 = state(0)
    s1 = state(1)
    s2 = state(2)
    s3 = state(3)
    s4 = state(4)
    s0.outpaths = {
        ('a', 'A'): {(s0, 'AA')},
        ('a', '$'): {(s0, 'A$')},
        ('b', 'A'): {(s1, 'ε')}
    }
    s1.outpaths = {('b', 'A'): {(s1, 'ε')}, ('c', '$'): {(s2, 'C$')}}
    s2.outpaths = {('c', 'C'): {(s2, 'CC')}, ('d', 'C'): {(s3, 'ε')}}
    s3.outpaths = {('d', 'C'): {(s3, 'ε')}, ('ε', '$'): {(s4, 'ε')}}
    p = PDA({s0, s1, s2, s3, s4})
    p.input_alphabet = {'a', 'b'}
    p.stack_symbols = {'$', 'A', 'B'}
    p.start_state = s0
    p.accept_states = {s4}
    p.to_cfg()
    p.my_cfg.print_converted_cfg()
Пример #8
0
 def plus(self, nfa_parts, finalize=False):
     if len(nfa_parts) == 1:
         if finalize:
             self.my_nfa.start_states = [nfa_parts[0][0]]
             self.my_nfa.accept_states = [nfa_parts[0][-1]]
         return nfa_parts[0]
     else:
         new_state = state(self.num)
         self.num += 1
         new_state.outpaths = {'ε': [states[0] for states in nfa_parts]}
         new_state2 = state(self.num)
         self.num += 1
         new_states = [new_state]
         for states in nfa_parts:
             if 'ε' not in states[-1].outpaths:
                 states[-1].outpaths['ε'] = [new_state2]
             else:
                 states[-1].outpaths['ε'].append(new_state2)
             new_states += states
         new_states += [new_state2]
         if finalize:
             self.my_nfa.start_states = [new_states[0]]
             self.my_nfa.accept_states = [new_states[-1]]
         return new_states
Пример #9
0
    def convert_to_pda(self):
        from automata.pda import PDA
        self.convert_to_gnf()

        s = state(0)
        p = PDA(set([s]), self.start)
        self.find_terms_nonterms()
        p.alphabet = self.terminals.difference(set(['ε']))
        p.stack_symbols = self.nonterminals.union(p.alphabet)
        terms = self.terminals.difference(set(['ε']))

        for t in terms:
            s.outpaths[(t, t)] = set([(s, 'ε')])

        for nt in self.nonterminals:
            prods = self.rules[nt]
            for str in prods:
                if ('ε', nt) in s.outpaths:
                    s.outpaths[('ε', nt)].add((s, str))
                else:
                    s.outpaths[('ε', nt)] = set([(s, str)])

        self.my_pda = p
        self.my_pda.start_state = s
Пример #10
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)

    """
Пример #11
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)

    """
Пример #12
0
    def minimize(self):
        i = 0
        for st in self.states:
            st.index = i
            i += 1

        num_states = len(self.states)
        self.matrix = [[None for _ in range(num_states)]
                       for _ in range(num_states)]

        for i in range(num_states):
            is_acc = True if self.states[i] in self.accept_states else False
            for j in range(i + 1, num_states):
                if self.states[j] in self.accept_states:
                    if not is_acc:
                        self.matrix[i][j] = 0
                else:
                    if is_acc:
                        self.matrix[i][j] = 0

        round_num = 1
        cont = True
        while cont:
            cont = False
            for i in range(num_states):
                for j in range(i + 1, num_states):
                    if self.matrix[i][j] is None:
                        for sym in self.alphabet:
                            s1 = self.states[i].outpaths[
                                sym] if sym in self.states[i].outpaths else None
                            s2 = self.states[j].outpaths[
                                sym] if sym in self.states[j].outpaths else None
                            if s1 is not None and s2 is not None:
                                max_index = max(s1.index, s2.index)
                                min_index = min(s1.index, s2.index)
                                if self.matrix[min_index][max_index] is not None and \
                                self.matrix[min_index][max_index] != round_num:
                                    #2nd condition not required but makes
                                    #for better distinction between rounds
                                    #maybe delete
                                    self.matrix[i][j] = round_num
                                    cont = True
                                    break
                            elif (s1 is None
                                  and s2 is not None) or (s1 is not None
                                                          and s2 is None):
                                self.matrix[i][j] = round_num
                                cont = True
                                break
            round_num += 1

        unique = 0
        count = 0
        for i in range(num_states):
            for j in range(i + 1, num_states):
                if self.matrix[i][j] is not None:
                    unique += 1
                count += 1

        if unique == count:
            print('Your DFA is already minimized.')
            return

        self.new_states = {}
        count = num_states
        for i in range(num_states):
            for j in range(i + 1, num_states):
                if self.matrix[i][j] is None:
                    found = False
                    for key, val in self.new_states.items():
                        if self.states[i] in val and self.states[j] not in val:
                            self.new_states[key].add(self.states[j])
                            found = True
                            break
                        elif self.states[j] in val and self.states[
                                i] not in val:
                            self.new_states[key].add(self.states[j])
                            found = True
                            break
                        elif self.states[j] in val and self.states[i] in val:
                            found = True
                            break
                    if not found:
                        self.new_states[state(count)] = {
                            self.states[i], self.states[j]
                        }
                        count += 1

        existing_states = set()
        for key, val in self.new_states.items():
            existing_states = existing_states.union(val)
        missing_states = set(self.states).difference(existing_states)

        for st in missing_states:
            if st.id != '∅':
                self.new_states[state(count)] = {st}
                count += 1
            else:
                self.new_states[st] = {st}

        self.new_start_state = None
        self.new_acc_states = []
        for new, old in self.new_states.items():
            for s in old:
                if s.id == self.start_state.id:
                    self.new_start_state = new
                if s in self.accept_states and new not in self.new_acc_states:
                    self.new_acc_states.append(new)
            for key, val in s.outpaths.items():
                for new2, old2 in self.new_states.items():
                    if val in old2:
                        new.outpaths[key] = new2

        self.states = [key for key in self.new_states]
        self.start_state = self.new_start_state
        self.accept_states = self.new_acc_states
        self.remove_unreachable()