13void print_set(
const DFASet& set) {
15 for (
auto state : set) std::cout << state->id() <<
", ";
20DFASet get_accepting_states(
const DFASet& reachableStates) {
22 for (
auto state : reachableStates)
23 if (state->is_accepting()) acceptingStates.insert(state);
24 return acceptingStates;
27DFASet get_erroring_states(
const DFASet& reachableStates) {
29 for (
auto state : reachableStates)
30 if (state->is_erroring()) erroringStates.insert(state);
31 return erroringStates;
34std::set<std::uint16_t> get_alphabet(
const DFASet& reachableStates) {
35 std::set<std::uint16_t> alphabet;
36 for (
auto state : reachableStates)
37 state->for_transitions([&](
auto c,
auto) { alphabet.insert(c); });
43 for (
auto state : lhs)
44 if (!rhs.contains(state)) result.insert(state);
49 for (
auto state : lhs)
50 if (rhs.contains(state)) result.insert(state);
54std::vector<DFASet> hopcroft(
const DFASet& reachableStates) {
55 const auto alphabet = get_alphabet(reachableStates);
57 const auto F = get_accepting_states(reachableStates);
58 const auto E = get_erroring_states(reachableStates);
60 assert((F * E).
empty() &&
"F and E must be disjoint");
62 std::vector<DFASet> P = {
F, E, reachableStates -
F - E};
63 std::vector<DFASet>
W = {
F, E, reachableStates -
F - E};
65 std::vector<DFASet> newP;
69 for (
const auto& S : P) print_set(S);
71 for (
const auto& S : W) print_set(S);
75 for (
auto c : alphabet) {
77 for (
const auto* state : reachableStates) {
78 state->for_transitions([&](
auto c_,
auto to) {
79 if (c_ == c && A.contains(to)) X.insert(state);
83 for (
const auto& Y : P) {
86 if (!YnX.empty() && !Y_X.empty()) {
89 if (
auto YWit = std::find(
W.begin(),
W.end(), Y); YWit !=
W.end()) {
94 if (YnX.size() <= Y_X.size())
116 const auto P = hopcroft(reachableStates);
118 auto minDfa = std::make_unique<DFA>();
121 auto state = minDfa->add_state();
123 if (x->is_accepting()) state->set_accepting(
true);
124 if (x->is_erroring()) state->set_erroring(
true);
125 dfaStates.emplace(x, state);
128 minDfa->set_start(dfaStates[dfa.
get_start()]);
131 auto state = dfaStates[*X.begin()];
133 x->for_transitions([&](
auto c,
auto to) { state->add_transition(dfaStates[to], c); });
std::set< const NodeType *, typename NodeType::Lt > get_reachable_states() const
Ordered by NodeType::Lt (i.e. by id) so that iteration is deterministic.
const NodeType * get_start() const
std::unique_ptr< DFA > minimize_dfa(const DFA &dfa)
std::set< const DFANode *, DFANode::Lt > DFASet
std::map< const DFANode *, To, DFANode::Lt > DFAMap