finite-automatacomputer-science-theoryfinite-state-automaton

Designing a DFA (alphabet 'a' and 'b') : The number of 'a' in the string must be a multiple of 3, and the string does not contain 'aba'


Here is the problem: enter image description here

And here is my line of reasoning when I first came upon it:

I had no choice but to use guesswork in order to arrive at a solution. Here is what I came up with (1,2,3 are finishing states, 3 is the start state, and also 7 and 9 both goes to 1 if an input 'a' is received): enter image description here I also used DFA minimization on this one, and found out that it is already minimal. However, the textbooks gives another solution: enter image description here

But I don't understand how it is correct! I just can't figure it out :(. And I don't even know if my solution is 100% correct. Please help me, thank you very much :)


Solution

  • Your answer seems to be correct. I haven't carefully proved it, but the logic is fairly clear. Furthermore, I wrote a Python program to test it:

    def accepts(transitions,initial,accepting,s):
        state = initial
        for c in s:
            state = transitions[state][c]
        return state in accepting
    
    dfa = {1:{'a':4, 'b':2},
           2:{'a':10, 'b':3},
           3:{'a':4, 'b':3},
           4:{'a':7, 'b':5},
           5:{'a':10, 'b':6},
           6:{'a':7, 'b':6},
           7:{'a':1, 'b':8},
           8:{'a':10, 'b':9},
           9:{'a':1, 'b':9},
           10:{'a':10, 'b':10}}
    
    def dfaTest(s):
        return accepts(dfa,3,{1,2,3},s)
    
    def valid(s):
        return s.count('a') % 3 == 0 and not 'aba' in s
    
    import random
    
    tests = [''.join(random.choice(['a','b']) for j in range(100)) for i in range(1,1001)]
    
    print(all(valid(s) == dfaTest(s) for s in tests))
    

    The operation of the function accepts is explained in this answer. I tailored it to match your diagram. To stress-test it I generated 100,000 random inputs whose length range from 1 to 1000 and then compared the output from the DFA with a direct verification of the condition. Every time I run this code, the output is a satisfying True.

    To test individual strings:

    >>> dfaTest('ababba')
    False
    >>> dfaTest('abbabba')
    True