7#include <absl/container/flat_hash_map.h>
15void print_set(
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)
39 state->for_transitions([&](
auto c,
auto) { alphabet.insert(c); });
43std::set<const DFANode*> operator-(
const std::set<const DFANode*>& lhs,
const std::set<const DFANode*>& rhs) {
44 std::set<const DFANode*> result;
45 for (
auto state : lhs)
46 if (!rhs.contains(state)) result.insert(state);
49std::set<const DFANode*> operator*(
const std::set<const DFANode*>& lhs,
const std::set<const DFANode*>& rhs) {
50 std::set<const DFANode*> result;
51 for (
auto state : lhs)
52 if (rhs.contains(state)) result.insert(state);
56std::vector<std::set<const DFANode*>> hopcroft(
const std::set<const DFANode*>& reachableStates) {
57 const auto alphabet = get_alphabet(reachableStates);
59 const auto F = get_accepting_states(reachableStates);
60 const auto E = get_erroring_states(reachableStates);
62 assert((F * E).
empty() &&
"F and E must be disjoint");
64 std::vector<std::set<const DFANode*>> P = {
F, E, reachableStates -
F - E};
65 std::vector<std::set<const DFANode*>>
W = {
F, E, reachableStates -
F - E};
67 std::vector<std::set<const DFANode*>> newP;
71 for (
const auto& S : P) print_set(S);
73 for (
const auto& S : W) print_set(S);
77 for (
auto c : alphabet) {
78 std::set<const DFANode*> X{};
79 for (
const auto* state : reachableStates) {
80 state->for_transitions([&](
auto c_,
auto to) {
81 if (c_ == c && A.contains(to)) X.insert(state);
85 for (
const auto& Y : P) {
88 if (!YnX.empty() && !Y_X.empty()) {
91 if (
auto YWit = std::find(
W.begin(),
W.end(), Y); YWit !=
W.end()) {
96 if (YnX.size() <= Y_X.size())
118 const auto P = hopcroft(reachableStates);
120 auto minDfa = std::make_unique<DFA>();
121 absl::flat_hash_map<const DFANode*, DFANode*> dfaStates;
123 auto state = minDfa->add_state();
125 if (x->is_accepting()) state->set_accepting(
true);
126 if (x->is_erroring()) state->set_erroring(
true);
127 dfaStates.emplace(x, state);
130 minDfa->set_start(dfaStates[dfa.
get_start()]);
133 auto state = dfaStates[*X.begin()];
135 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)