TEST_F(TestDFA, Equivalence) { instance << "q0"; instance << "q1"; instance.addTransition("q0", "q1", 'a'); instance.accept("q1"); DFA copy; ASSERT_NO_THROW(copy = ~~instance); ASSERT_EQ(instance.size(), copy.size()); DFA almostEqual; almostEqual << "q0"; almostEqual << "q1"; almostEqual.addTransition("q0", "q1", 'b'); almostEqual.accept("q1"); bool r; ASSERT_NO_THROW(r = (copy == instance)); EXPECT_TRUE(r); EXPECT_EQ(2, instance.size()); EXPECT_EQ(2, copy.size()); ASSERT_NO_THROW(r = (almostEqual == instance)); EXPECT_FALSE(r); EXPECT_EQ(2, instance.size()); EXPECT_EQ(2, almostEqual.size()); }
TEST_F(TestDFA, Containment) { instance << "q0"; instance << "q1"; instance << "q2"; instance << "q3"; instance.addTransition("q0", "q1", 'a'); instance.addTransition("q0", "q1", 'b'); instance.addTransition("q1", "q2", 'a'); instance.addTransition("q1", "q2", 'b'); instance.addTransition("q2", "q3", 'a'); instance.addTransition("q2", "q3", 'b'); instance.addTransition("q3", "q0", 'a'); instance.addTransition("q3", "q0", 'b'); instance.accept("q0"); instance.accept("q2"); DFA second; second << "q0"; second << "q1"; second.addTransition("q0", "q1", 'a'); second.addTransition("q1", "q0", 'a'); second.accept("q0"); bool r1, r2; ASSERT_NO_THROW(r1 = instance.contains(second)); ASSERT_NO_THROW(r2 = second.contains(instance)); EXPECT_TRUE(r1); EXPECT_FALSE(r2); EXPECT_EQ(4, instance.size()); EXPECT_EQ(2, second.size()); }
TEST_F(TestDFA, Union) { instance << "q0"; instance << "q1"; instance << "q2"; instance.addTransition("q0", "q1", 'a'); instance.addTransition("q1", "q2", 'a'); instance.addTransition("q2", "q0", 'a'); instance.accept("q0"); DFA second; second << "q0"; second << "q1"; second.addTransition("q0", "q1", 'a'); second.addTransition("q1", "q0", 'a'); second.accept("q0"); DFA unionDFA = instance | second; EXPECT_EQ(3, instance.size()); EXPECT_EQ(2, second.size()); EXPECT_EQ(6, unionDFA.size()); EXPECT_TRUE(unionDFA.accepts()); unionDFA.read("a"); EXPECT_FALSE(unionDFA.accepts()); unionDFA.read("a"); EXPECT_TRUE(unionDFA.accepts()); unionDFA.read("a"); EXPECT_TRUE(unionDFA.accepts()); unionDFA.read("a"); EXPECT_TRUE(unionDFA.accepts()); unionDFA.read("a"); EXPECT_FALSE(unionDFA.accepts()); unionDFA.read("a"); EXPECT_TRUE(unionDFA.accepts()); }
TEST_F(TestDFA, Intersection) { instance << "q0"; instance << "q1"; instance << "q2"; instance.addTransition("q0", "q1", 'a'); instance.addTransition("q1", "q2", 'a'); instance.addTransition("q2", "q0", 'a'); instance.accept("q0"); DFA second; second << "q0"; second << "q1"; second.addTransition("q0", "q1", 'a'); second.addTransition("q1", "q0", 'a'); second.accept("q0"); DFA intersection = instance & second; EXPECT_EQ(3, instance.size()); EXPECT_EQ(2, second.size()); EXPECT_EQ(6, intersection.size()); EXPECT_TRUE(intersection.accepts()); intersection.read("a"); EXPECT_FALSE(intersection.accepts()); intersection.read("a"); EXPECT_FALSE(intersection.accepts()); intersection.read("a"); EXPECT_FALSE(intersection.accepts()); intersection.read("a"); EXPECT_FALSE(intersection.accepts()); intersection.read("a"); EXPECT_FALSE(intersection.accepts()); intersection.read("a"); EXPECT_TRUE(intersection.accepts()); }
TEST_F(TestDFA, RValueOperations) { DFA first; first << "q0" << "q1" << "q2"; first.addTransition("q0", "q1", 'a'); first.addTransition("q1", "q2", 'a'); first.addTransition("q2", "q0", 'a'); first.accept("q0"); DFA second; second << "q0" << "q1"; second.addTransition("q0", "q1", 'a'); second.addTransition("q1", "q0", 'a'); second.accept("q1"); EXPECT_NO_THROW(first & ~second); EXPECT_NO_THROW(first | ~second); EXPECT_NO_THROW(first == ~second); EXPECT_NO_THROW(first.contains(~second)); EXPECT_NO_THROW(second.contains(~first)); }
DFA DFA::FROM_NFA(NFA nfa){ DFA dfa; NFATable nfa_table = nfa.getTable(); fa_table nfa_table_map = nfa_table.getMapping(); unordered_set<string> visited; int_set first_set = nfa_table_map[0][Symbol::EPSILON]; queue<int_set> set_queue= queue<int_set>{{first_set}}; // set_queue.push(first_set); int dfa_state_count = 0; string set_name = Utils::TO_STRING(first_set); unordered_map<string, int> dfa_state_mapping = unordered_map<string, int> {{ set_name, 0 }}; dfa.addState("q" + to_string(0)); int nfa_state_count = nfa_table_map.size(); while (!set_queue.empty()){ int_set curr_state_set = set_queue.front(); set_queue.pop(); // set_name = Utils::TO_STRING(curr_state_set); string state_name = Utils::TO_STRING(curr_state_set); if (visited.find(state_name) != visited.end()) continue; visited.insert(state_name); bool is_final_state = false; { bool states_visited[nfa_state_count] = { 0 }; for (auto st : curr_state_set) states_visited[st] = true; for (auto curr_state : curr_state_set){ int_set e_closure = nfa_table_map[curr_state][Symbol::EPSILON]; for (auto e_closure_state : e_closure){ if (!states_visited[e_closure_state]){ curr_state_set.insert(e_closure_state); states_visited[e_closure_state] = true; } } } // delete states_visited; } for (auto symbol : nfa_table.getAlphabet()){ if (symbol == Symbol::EPSILON) continue; int_set next_set; bool states_visited[nfa_state_count] = { 0 }; for (auto curr_state : curr_state_set){ if (!is_final_state && curr_state == nfa_table.getFinalState()) is_final_state = true; if (nfa_table_map[curr_state].find(symbol) != nfa_table_map[curr_state].end()){ int_set next_states = nfa_table_map[curr_state][symbol]; for (auto ns : next_states){ int_set e_closure = nfa_table_map[ns][Symbol::EPSILON]; for (auto e_closure_state : e_closure){ if (!states_visited[e_closure_state]){ next_set.insert(e_closure_state); states_visited[e_closure_state] = true; } } } } } string next_state_name = Utils::TO_STRING(next_set); if (next_set.size() > 0){ if (dfa_state_mapping.find(next_state_name) == dfa_state_mapping.end()){ // dfa.addState(next_state_name); dfa_state_count++; dfa.addState("q" + to_string(dfa_state_count)); dfa_state_mapping.insert({next_state_name, dfa_state_count}); } dfa.addTransition(dfa_state_mapping[state_name], dfa_state_mapping[next_state_name], symbol); } // else{ // dfa.addTransition(dfa_state_mapping[state_name], 0, symbol); // } if (is_final_state) dfa.addFinalState(dfa_state_mapping[state_name]); if (next_set.size() > 0 && visited.find(next_state_name) == visited.end()){ set_queue.push(next_set); } // delete states_visited; } } return dfa; }