def test_grammar_to_automata(self):
        delta = self.grammar.to_automata()
        ndfa = NDFA(delta, "S1", ["qAccept"])

        self.assertTrue(ndfa.validate_sentence("aabbbbcc"))
        self.assertFalse(ndfa.validate_sentence("aaccbb"))

        dfa = ndfa.determinization()

        self.assertTrue(ndfa.validate_sentence("aabbbbcc"))
        self.assertFalse(ndfa.validate_sentence("aaccbb"))

        regular = dfa.to_grammar()
    def setUp(self):
        """delta table
           L = { a+ or (ab)+ }

           delta |    a   |   b   |
           ------|--------|-------|
            ->q0 | q1,q2  |   -   |
             *q1 |   q1   |   -   |
              q2 |   -    |  q3   |
             *q3 |   q2   |   -   |
           -----------------------|
        """
        self.delta = {
            'q0': {'a': {'q1', 'q2'}},
            'q1': {'a': {'q1'}},
            'q2': {'b': {'q3'}},
            'q3': {'a': {'q2'}}
        }

        initial_state = 'q0'
        accept_states = ['q1', 'q3']
        self.ndfa = NDFA(self.delta, initial_state, accept_states)
class NDFATests(unittest.TestCase):
    def setUp(self):
        """delta table
           L = { a+ or (ab)+ }

           delta |    a   |   b   |
           ------|--------|-------|
            ->q0 | q1,q2  |   -   |
             *q1 |   q1   |   -   |
              q2 |   -    |  q3   |
             *q3 |   q2   |   -   |
           -----------------------|
        """
        self.delta = {
            'q0': {'a': {'q1', 'q2'}},
            'q1': {'a': {'q1'}},
            'q2': {'b': {'q3'}},
            'q3': {'a': {'q2'}}
        }

        initial_state = 'q0'
        accept_states = ['q1', 'q3']
        self.ndfa = NDFA(self.delta, initial_state, accept_states)

    def create_epsilon_ndfa(self):
        """ delta table
            L = { #a=pair xor #b=par }
            delta |    a   |   b   |   &   |
            ------|--------|-------|-------|
             ->q0 |    -   |   -   | q1,q3 |
              *q1 |   q2   |   -   |   -   |
               q2 |   q1   |   -   |   -   |
              *q3 |    -   |   q4  |   -   |
               q4 |    -   |   q3  |   -   |
            -------------------------------|

        :return:{NDFA} non epsilon free
        """
        initial_state = 'q0'
        accept_states = ['q1', 'q3']

        delta_with_epsilon = {
            'q0': {'&': {'q1', 'q3'}},
            'q1': {'a': {'q2'}},
            'q2': {'a': {'q1'}},
            'q3': {'b': {'q4'}},
            'q4': {'b': {'q3'}}
        }

        return NDFA(delta_with_epsilon, initial_state, accept_states)

    def expected_dfa(self):
        """ create DFA to help the tests
            new_delta |     a    |     b    |
           -----------|----------|----------|
              ->{q0}  | {q1,q2}  |     -    |
              *{q1,q2}|   {q1}   |   {q3}   |
               *{q1}  |   {q1}   |     -    |
               *{q3}  |   {q2}   |     -    |
                {q2}  |     -    |   {q3}   |
           ---------------------------------|
        :return: {DFA}
        """
        # It's needed use frozenset on states to iterate by element in DFA
        # for not use iterate in hashes
        delta = {frozenset({'q0'}): {'a': frozenset({'q1','q2'})},
                 frozenset({'q1', 'q2'}): {'a': frozenset({'q1'}), 'b': frozenset({'q3'})},
                 frozenset({'q1'}): {'a': frozenset({'q1'})},
                 frozenset({'q3'}): {'a': frozenset({'q2'})},
                 frozenset({'q2'}): {'b': frozenset({'q3'})}}

        initial_state = frozenset({'q0'})
        accept_states = [frozenset({'q1', 'q2'}),
                         frozenset({'q1'}),
                         frozenset({'q3'})]

        return DFA(delta, initial_state, accept_states)

    def expected_dfa_epsilon_free(self):
        """ create DFA to help the tests
             new_delta  |   a  |   b  |
           -------------|------|------|
           ->*{q0,q1,q3}| {q2} | {q4} |
                    {q2}| {q1} |   -  |
                    {q4}|   -  | {q3} |
                   *{q1}| {q2} |   -  |
                   *{q3}|   -  | {q4} |
           ---------------------------|
        :return: {DFA}
        """
        # It's needed use frozenset on states to iterate by element in DFA
        # for not use iterate in hashes
        delta = {frozenset({'q0','q1','q3'}): {'a': frozenset({'q2'}), 'b': frozenset({'q4'})},
                 frozenset({'q2'}): {'a': frozenset({'q1'})},
                 frozenset({'q4'}): {'b': frozenset({'q3'})},
                 frozenset({'q1'}): {'a': frozenset({'q2'})},
                 frozenset({'q3'}): {'b': frozenset({'q4'})}}

        initial_state = frozenset({'q0','q1','q3'})
        accept_states = [frozenset({'q0','q1','q3'}),
                         frozenset({'q1'}),
                         frozenset({'q3'})]

        return DFA(delta, initial_state, accept_states)

    def test_accept_sentence_aaa(self):
        """
        DFA accept sentence 'aaa'
        """
        is_accept = self.ndfa.validate_sentence('aaa')
        self.assertTrue(is_accept)

    def test_accept_sentence_ababab(self):
        """
        DFA accept sentence 'ababab'
        """
        is_accept = self.ndfa.validate_sentence('ababab')
        self.assertTrue(is_accept)

    def test_reject_sentence_aaabab(self):
        """
        DFA reject sentence 'aaabab'
        """
        is_accept = self.ndfa.validate_sentence('aaabab')
        self.assertFalse(is_accept)

    def test_get_alphabet_from_NDFA(self):
        """
        get alphabet from DFA
        alphabet = {a, b}
        """
        sigma = self.ndfa.get_alphabet()
        self.assertSetEqual({'a', 'b'}, sigma)

    def test_get_states_from_NDFA(self):
        """
        get states from DFA
        states {q0, q1}
        """
        states = self.ndfa.get_states()
        self.assertSetEqual({'q0', 'q1', 'q2', 'q3'}, states)

    def test_determinization(self):
        """new delta table determinate

            transform this NDFA to compatible DFA
            L = { a+ or (ab)+ }

            delta |    a   |   b   |             new_delta |     a    |     b    |
            ------|--------|-------|              ---------|----------|----------|
             ->q0 | q1,q2  |   -   |       \       ->{q0}  | {q1,q2}  |     -    |
              *q1 |   q1   |   -   |    ----\      *{q1,q2}|   {q1}   |   {q3}   |
               q2 |   -    |  q3   |    ----/       *{q1}  |   {q1}   |     -    |
              *q3 |   q2   |   -   |       /        *{q3}  |   {q2}   |     -    |
            -----------------------|                 {q2}  |     -    |   {q3}   |
                                                  -------------------------------|
        """
        ndfa_determinized = self.ndfa.determinization()

        self.assertIsInstance(ndfa_determinized, DFA)

        expected_dfa = self.expected_dfa()
        self.assertDictEqual(expected_dfa.delta, ndfa_determinized.delta) # check delta transitions
        self.assertSetEqual(expected_dfa.accept_states, ndfa_determinized.accept_states) # check accept states
        self.assertEqual(expected_dfa.initial_state, ndfa_determinized.initial_state) # check initial state

        # check states and alphabet from DFA generated
        self.assertSetEqual(expected_dfa.get_states(), ndfa_determinized.get_states())
        self.assertSetEqual(expected_dfa.get_alphabet(), ndfa_determinized.get_alphabet())

        # validate sentences 'aaa' and 'ababab'
        self.assertTrue(ndfa_determinized.validate_sentence('ababab'))
        self.assertTrue(ndfa_determinized.validate_sentence('aaa'))

        # reject sentence 'aaabab'
        self.assertFalse(ndfa_determinized.validate_sentence('aaabab'))

    def test_determinization_epsilon_NDFA(self):
        """new delta table determinate
            transform this epsilon-NDFA to compatible DFA
            L = { #a=pair xor #b=par }


            delta |    a   |   b   |   &   |             new_delta  |   a  |   b  |
            ------|--------|-------|-------|           -------------|------|------|
             ->q0 |    -   |   -   | q1,q3 |      \    ->*{q0,q1,q3}| {q2} | {q4} |
              *q1 |   q2   |   -   |   -   |   ----\            {q2}| {q1} |   -  |
               q2 |   q1   |   -   |   -   |   ----/            {q4}|   -  | {q3} |
              *q3 |    -   |   q4  |   -   |      /            *{q1}| {q2} |   -  |
               q4 |    -   |   q3  |   -   |                   *{q3}|   -  | {q4} |
            -------------------------------|           ---------------------------|

        """
        epsilon_ndfa = self.create_epsilon_ndfa()
        epsilon_ndfa_determinized = epsilon_ndfa.determinization()

        self.assertIsInstance(epsilon_ndfa_determinized, DFA)

        expected_dfa = self.expected_dfa_epsilon_free()
        self.assertDictEqual(expected_dfa.delta, epsilon_ndfa_determinized.delta) # check delta transitions
        self.assertSetEqual(expected_dfa.accept_states, epsilon_ndfa_determinized.accept_states) # check accept states
        self.assertEqual(expected_dfa.initial_state, epsilon_ndfa_determinized.initial_state) # check initial state

        # check states and alphabet from DFA generated
        self.assertSetEqual(expected_dfa.get_states(), epsilon_ndfa_determinized.get_states())
        self.assertSetEqual(expected_dfa.get_alphabet(), epsilon_ndfa_determinized.get_alphabet())

        # validate sentences 'empty('')', 'aa' and 'bbbb'
        self.assertTrue(epsilon_ndfa_determinized.validate_sentence(''))
        self.assertTrue(epsilon_ndfa_determinized.validate_sentence('aa'))
        self.assertTrue(epsilon_ndfa_determinized.validate_sentence('bbbb'))

        # reject sentence 'aaa'
        self.assertFalse(epsilon_ndfa_determinized.validate_sentence('aaa'))

    def test_epsilon_closure_from_q0(self):
        epsilon_ndfa = self.create_epsilon_ndfa()
        _epsilon_closure = epsilon_ndfa.epsilon_closure('q0')
        expected_closure = {'q0','q1','q3'}
        self.assertSetEqual(expected_closure, _epsilon_closure)