7#include <absl/container/flat_hash_map.h>
15void printSet(
const std::set<const DFANode*>& set) {
17 for (
auto state : set) std::cout << state <<
", ";
22std::set<const DFANode*> get_accepting_states(
const std::set<const DFANode*>& reachableStates) {
23 std::set<const DFANode*> acceptingStates;
24 for (
auto state : reachableStates)
25 if (state->is_accepting()) acceptingStates.insert(state);
26 return acceptingStates;
29std::set<const DFANode*> get_erroring_states(
const std::set<const DFANode*>& reachableStates) {
30 std::set<const DFANode*> erroringStates;
31 for (
auto state : reachableStates)
32 if (state->is_erroring()) erroringStates.insert(state);
33 return erroringStates;
36std::set<std::uint16_t> get_alphabet(
const std::set<const DFANode*>& reachableStates) {
37 std::set<std::uint16_t> alphabet;
38 for (
auto state : reachableStates) state->for_transitions([&](
auto c,
auto) { alphabet.insert(c); });
42std::set<const DFANode*> operator-(
const std::set<const DFANode*>& lhs,
const std::set<const DFANode*>& rhs) {
43 std::set<const DFANode*> result;
44 for (
auto state : lhs)
45 if (!rhs.contains(state)) result.insert(state);
48std::set<const DFANode*> operator*(
const std::set<const DFANode*>& lhs,
const std::set<const DFANode*>& rhs) {
49 std::set<const DFANode*> result;
50 for (
auto state : lhs)
51 if (rhs.contains(state)) result.insert(state);
55std::vector<std::set<const DFANode*>> hopcroft(
const std::set<const DFANode*>& reachableStates) {
56 const auto alphabet = get_alphabet(reachableStates);
58 const auto F = get_accepting_states(reachableStates);
59 const auto E = get_erroring_states(reachableStates);
61 assert((F * E).empty() &&
"F and E must be disjoint");
63 std::vector<std::set<const DFANode*>> P = {
F, E, reachableStates -
F - E};
64 std::vector<std::set<const DFANode*>>
W = {
F, E, reachableStates -
F - E};
66 std::vector<std::set<const DFANode*>> newP;
70 for (
const auto& S : P) printSet(S);
72 for (
const auto& S : W) printSet(S);
76 for (
auto c : alphabet) {
77 std::set<const DFANode*> X{};
78 for (
const auto* state : reachableStates) {
79 state->for_transitions([&](
auto c_,
auto to) {
80 if (c_ == c && A.contains(to)) X.insert(state);
84 for (
const auto& Y : P) {
87 if (!YnX.empty() && !Y_X.empty()) {
90 if (
auto YWit = std::find(
W.begin(),
W.end(), Y); YWit !=
W.end()) {
95 if (YnX.size() <= Y_X.size())
117 const auto P = hopcroft(reachableStates);
119 auto minDfa = std::make_unique<DFA>();
120 absl::flat_hash_map<const DFANode*, DFANode*> dfaStates;
122 auto state = minDfa->add_state();
124 if (x->is_accepting()) state->set_accepting(
true);
125 if (x->is_erroring()) state->set_erroring(
true);
126 dfaStates.emplace(x, state);
129 minDfa->set_start(dfaStates[dfa.
get_start()]);
132 auto state = dfaStates[*X.begin()];
133 for (
auto x : X) x->for_transitions([&](
auto c,
auto to) { state->add_transition(dfaStates[to], c); });
const NodeType * get_start() const
std::set< const NodeType * > get_reachable_states() const
std::unique_ptr< DFA > minimize_dfa(const DFA &dfa)