12DFASet get_accepting_states(
const DFASet& reachableStates) {
14 for (
auto state : reachableStates)
15 if (state->is_accepting()) acceptingStates.insert(state);
16 return acceptingStates;
19DFASet get_erroring_states(
const DFASet& reachableStates) {
21 for (
auto state : reachableStates)
22 if (state->is_erroring()) erroringStates.insert(state);
23 return erroringStates;
26std::set<std::uint16_t> get_alphabet(
const DFASet& reachableStates) {
27 std::set<std::uint16_t> alphabet;
28 for (
auto state : reachableStates)
29 state->for_transitions([&](
auto c,
auto) { alphabet.insert(c); });
35 for (
auto state : lhs)
36 if (!rhs.contains(state)) result.insert(state);
41 for (
auto state : lhs)
42 if (rhs.contains(state)) result.insert(state);
46std::vector<DFASet> hopcroft(
const DFASet& reachableStates) {
47 const auto alphabet = get_alphabet(reachableStates);
49 const auto F = get_accepting_states(reachableStates);
50 const auto E = get_erroring_states(reachableStates);
52 assert((F * E).
empty() &&
"F and E must be disjoint");
55 auto P = std::vector<DFASet>();
56 for (
auto&& S : {
F, E, reachableStates -
F - E})
57 if (!
S.empty()) P.push_back(S);
60 std::vector<DFASet> newP;
64 for (
auto c : alphabet) {
66 for (
const auto* state : reachableStates) {
67 state->for_transitions([&](
auto c_,
auto to) {
68 if (c_ == c && A.contains(to)) X.insert(state);
72 for (
const auto& Y : P) {
75 if (!YnX.empty() && !Y_X.empty()) {
78 if (
auto YWit = std::find(
W.begin(),
W.end(), Y); YWit !=
W.end()) {
83 if (YnX.size() <= Y_X.size())
105 const auto P = hopcroft(reachableStates);
107 auto minDfa = std::make_unique<DFA>();
110 auto state = minDfa->add_state();
112 if (x->is_accepting()) state->set_accepting(
true);
113 if (x->is_erroring()) state->set_erroring(
true);
114 dfaStates.emplace(x, state);
117 minDfa->set_start(dfaStates[dfa.
get_start()]);
119 auto state = dfaStates[*X.begin()];
121 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