def test_minimiza_retorna_classes_para_novo_automato_nao_deterministico(self):
        from Automaton import Automaton
        fa = Automaton()

        fa.set_alphabet(('a','b'))
        fa.set_states(('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'))
        fa.set_initial_state('A')
        fa.set_final_states(('A','D','G'))

        fa.add_transition('A', 'a', 'G')
        fa.add_transition('A', 'b', 'B')

        fa.add_transition('B', 'a', 'F')
        fa.add_transition('B', 'b', 'E')
        fa.add_transition('C', 'a', 'C')
        fa.add_transition('C', 'b', 'G')
        fa.add_transition('D', 'a', 'A')
        fa.add_transition('D', 'b', 'H')
        fa.add_transition('E', 'a', 'E')
        fa.add_transition('E', 'b', 'A')
        fa.add_transition('F', 'a', 'B')
        fa.add_transition('F', 'b', 'C')

        fa.add_transition('G', 'a', 'G')
        fa.add_transition('G', 'b', 'F')

        fa.add_transition('H', 'a', 'H')
        fa.add_transition('H', 'b', 'D')

        self.finite_automaton = fa.determinizar()
        achievable = self.finite_automaton._achievable_states()
        live_states = self.finite_automaton._live_states(achievable)

        self.assertEqual(self.finite_automaton.minimize(live_states), [['A', 'G'], ['B', 'F'], ['C', 'E']])
    def test_vivos_nao_deterministico(self):
        from Automaton import Automaton
        at = Automaton()

        at.set_alphabet(("a","b","c"))
        at.set_states(("S","A","B","C","F"))
        a = at.set_initial_state("S")
        at.set_final_states(("S","F"))

        at.add_transition("S","a","A")
        at.add_transition("S","b","B")
        at.add_transition("S","b","F")
        at.add_transition("S","c","S")
        at.add_transition("S","c","F")

        at.add_transition("A","a","S")
        at.add_transition("A","a","F")
        at.add_transition("A","b","C")
        at.add_transition("A","c","A")

        at.add_transition("B","a","A")
        at.add_transition("B","c","S")
        at.add_transition("B","c","B")
        at.add_transition("B","c","F")

        at.add_transition("C","a","S")
        at.add_transition("C","a","F")
        at.add_transition("C","c","A")
        at.add_transition("C","c","C")

        self.finite_automaton = at.determinizar()
        alcancaveis = self.finite_automaton._achievable_states()
        self.assertEqual(self.finite_automaton._live_states(alcancaveis),{"S","A","BF","FS","C","BFS","AC"})
class TestAutomaton(unittest.TestCase):
    def setUp(self):
        self.automaton =  Automaton()
        self.automaton2 = Automaton()

    def test_retorna_false_se_nao_definir_os_estados(self):
        self.automaton.set_alphabet(("a"))
        self.assertFalse(self.automaton.add_transition("A","a","B"))

    def test_retorna_false_se_nao_definir_o_alfabeto(self):
        self.automaton.set_states(("A","B"))
        self.assertFalse(self.automaton.add_transition("A","a","B"))

    def test_adiciona_transicao_nao_deterministica(self):
        self.automaton.set_alphabet(("a"))
        self.automaton.set_states(("A","B"))
        self.assertTrue(self.automaton.add_transition("A","a","B"))

    def test_retorna_as_transicoes_corretamente(self):
        expected = {'A':{'a':['B','C']}}

        self.automaton.set_alphabet(("a"))
        self.automaton.set_states(("A","B","C"))
        self.automaton.add_transition("A","a","B")
        self.automaton.add_transition("A","a","C")

        self.assertEqual(self.automaton.transitions, expected)

    def test_retorna_false_se_nao_tem_transicoes(self):
        self.assertFalse(self.automaton.determinizar())

    def test_retorna_transicoes_deterministicas_submetendo_AFND(self):
        expected = {'A':{'a':'BC'}, 'BC':{'a':'BC'}}

        self.automaton.set_alphabet(("a"))
        self.automaton.set_states(("A","B","C"))
        self.automaton.add_transition("A","a","B")
        self.automaton.add_transition("A","a","C")
        self.automaton.add_transition("B","a","B")
        self.automaton.add_transition("C","a","C")
        self.automaton.set_initial_state("A")
        self.automaton.set_final_states(("A"))

        self.assertEqual(self.automaton.determinizar().get_transitions(), expected)

    def test_deterministic_retorna_false_se_nao_tem_alfabeto(self):
        self.assertFalse(self.automaton.is_deterministic())

    def test_deterministic_retorna_false_se_nao_tem_transicoes(self):
        self.automaton.set_alphabet(("a"))
        self.assertFalse(self.automaton.is_deterministic())

    def test_deterministic_retorna_false_se_nao_tem_estados_finais(self):
        self.automaton.set_alphabet("a")
        self.automaton.set_states("A")
        self.automaton.add_transition("A","a","A")
        self.assertFalse(self.automaton.is_deterministic())

    def test_deterministic_retorna_false_se_nao_tem_estado_inicial(self):
        self.automaton.set_alphabet("a")
        self.automaton.set_states("A")
        self.automaton.set_final_states(("A"))
        self.automaton.add_transition("A","a","A")
        self.assertFalse(self.automaton.is_deterministic())

    def test_retorna_false_se_AF_eh_nao_deterministico(self):
        self.automaton.set_alphabet("a")
        self.automaton.set_states(("A","B"))
        self.automaton.set_final_states(("A"))
        self.automaton.set_initial_state("A")
        self.automaton.add_transition("A","a","A")
        self.automaton.add_transition("A","a","B")

        self.assertFalse(self.automaton.is_deterministic())

    def test_retorna_true_se_AF_eh_deterministico(self):
        self.automaton.set_alphabet("a")
        self.automaton.set_states(("A","B"))
        self.automaton.set_final_states(("A"))
        self.automaton.set_initial_state("A")
        self.automaton.add_transition("A","a","A")

        self.assertTrue(self.automaton.is_deterministic())

    def test_retorna_transicoes_deterministicas_submetendo_AFD(self):

        from FiniteAutomaton import FiniteAutomaton
        fa = FiniteAutomaton()
        fa.set_alphabet(("a"))
        fa.set_states(("A","B","C"))
        fa.set_initial_state("A")
        fa.set_final_states(("A"))

        fa.add_transition("A","a","B")
        fa.add_transition("B","a","B")
        fa.add_transition("C","a","C")

        self.automaton.set_alphabet(("a"))
        self.automaton.set_states(("A","B","C"))
        self.automaton.add_transition("A","a","B")
        self.automaton.add_transition("B","a","B")
        self.automaton.add_transition("C","a","C")
        self.automaton.set_initial_state("A")
        self.automaton.set_final_states(("A"))

        self.assertEqual(self.automaton.determinizar().get_transitions(), fa.get_transitions())


    def test_completion(self):
        self.automaton.set_alphabet(("a", "b"))
        self.automaton.set_states(("A", "B", "C"))
        self.automaton.add_transition("A", "a", "B")
        self.automaton.add_transition("B", "b", "B")
        self.automaton.add_transition("C", "a", "C")
        self.automaton.set_initial_state("A")
        self.automaton.set_final_states(("C"))
        self.assertTrue(self.automaton.completion())

    def test_complement(self):
        self.automaton.set_alphabet(("a", "b"))
        self.automaton.set_states(("A", "B", "C"))
        self.automaton.add_transition("A", "a", "B")
        self.automaton.add_transition("B", "b", "C")
        self.automaton.add_transition("C", "a", "C")
        self.automaton.set_initial_state("A")
        self.automaton.set_final_states(("C"))
        # self.assertTrue(self.automaton.complement())

    def test_union(self):
        self.automaton.set_alphabet(("a", "b"))
        self.automaton.set_states(("A", "B", "C"))
        self.automaton.add_transition("A", "a", "B")
        self.automaton.add_transition("B", "b", "C")
        self.automaton.add_transition("C", "a", "C")
        self.automaton.set_initial_state("A")
        self.automaton.set_final_states(("C"))

        self.automaton2.set_alphabet(("a", "b"))
        self.automaton2.set_states(("A", "B", "C"))
        self.automaton2.add_transition("A", "a", "B")
        self.automaton2.add_transition("B", "b", "C")
        self.automaton2.add_transition("C", "a", "C")
        self.automaton2.set_initial_state("A")
        self.automaton2.set_final_states(("C"))

        # self.assertTrue(self.automaton.union(self.automaton2))

    def test_intersection(self):
        self.automaton.set_alphabet(("a", "b"))
        self.automaton.set_states(("A", "B", "C"))
        self.automaton.add_transition("A", "a", "B")
        self.automaton.add_transition("B", "b", "C")
        self.automaton.add_transition("C", "a", "C")
        self.automaton.set_initial_state("A")
        self.automaton.set_final_states(("C"))

        self.automaton2.set_alphabet(("a", "b", "c"))
        self.automaton2.set_states(("A", "B", "C"))
        self.automaton2.add_transition("A", "a", "A")
        self.automaton2.add_transition("A", "a", "B")
        self.automaton2.add_transition("B", "b", "C")
        self.automaton2.add_transition("C", "c", "C")
        self.automaton2.set_initial_state("A")
        self.automaton2.set_final_states(("C"))

        self.assertTrue(self.automaton.intersection(self.automaton2))

    def test_retorna_transicoes_deterministicas_submetendo_AFD_alfabeto_ab(self):
        from FiniteAutomaton import FiniteAutomaton

        fa = FiniteAutomaton()
        fa.set_alphabet(("a","b"))
        fa.set_states(("S","BDF","ACF"))
        fa.set_initial_state("S")
        fa.set_final_states(("BDF","ACF"))

        fa.add_transition("S","a","BDF")
        fa.add_transition("BDF","a","ACF")
        fa.add_transition("ACF","a","BDF")

        fa.add_transition("S","b","ACF")
        fa.add_transition("BDF","b","BDF")
        fa.add_transition("ACF","b","ACF")

        #mock
        self.automaton.set_alphabet(("a","b"))
        self.automaton.set_states(("S","A","B","C","D","F"))

        self.automaton.add_transition("S","a","B")
        self.automaton.add_transition("S","a","D")
        self.automaton.add_transition("S","a","F")
        self.automaton.add_transition("S","b","A")
        self.automaton.add_transition("S","b","C")
        self.automaton.add_transition("S","b","F")


        self.automaton.add_transition("A","a","B")
        self.automaton.add_transition("A","a","F")
        self.automaton.add_transition("A","b","A")


        self.automaton.add_transition("B","a","A")
        self.automaton.add_transition("B","b","B")
        self.automaton.add_transition("B","b","F")


        self.automaton.add_transition("C","a","D")
        self.automaton.add_transition("C","b","C")
        self.automaton.add_transition("C","b","F")


        self.automaton.add_transition("D","a","C")
        self.automaton.add_transition("D","a","F")
        self.automaton.add_transition("D","b","D")

        self.automaton.set_initial_state("S")
        self.automaton.set_final_states(("F"))

        #assert
        self.assertEqual(self.automaton.determinizar().get_transitions(), fa.get_transitions())