Skip to content

Commit

Permalink
new minimize dispatch
Browse files Browse the repository at this point in the history
  • Loading branch information
koniksedy committed Dec 3, 2024
1 parent 0c35b01 commit 52222c3
Show file tree
Hide file tree
Showing 7 changed files with 24 additions and 71 deletions.
43 changes: 6 additions & 37 deletions include/mata/nfa/nfa.hh
Original file line number Diff line number Diff line change
Expand Up @@ -669,54 +669,23 @@ Nfa complement(const Nfa& aut, const utils::OrdVector<Symbol>& symbols,
/**
* @brief Compute minimal deterministic automaton.
*
* @param[in] aut Automaton whose minimal version to compute.
* @param[in] property Property of the automaton to minimize.
* - AutomatonProperty::Trimmed - Trim will not be performed.
* @param[in] params Optional parameters to control the minimization algorithm:
* - "algorithm": "brzozowski" (Default: "brzozowski")
* @return Minimal deterministic automaton.
*/
Nfa minimize_nfa(const Nfa& aut, const ParameterMap& params = { { "algorithm", "brzozowski" } });

/**
* @brief Compute minimal deterministic automaton.
*
* @param[in] aut Deterministic automaton whose minimal version to compute.
* @param[in] property Property of the automaton to minimize.
* - AutomatonProperty::Trimmed - Trim will not be performed.
* @param[in] params Optional parameters to control the minimization algorithm:
* - "algorithm": "hopcroft", "brzozowski" (Default: "hopcroft")
* @return Minimal deterministic automaton.
*/
Nfa minimize_dfa(const Nfa &aut,
const std::optional<AutomatonProperty> property,
const ParameterMap& params = { { "algorithm", "hopcroft" } });

/**
* @brief Compute minimal deterministic automaton.
*
* @param[in] aut Automaton whose minimal version to compute.
* @param[in] type Type of the automaton to minimize (NFA or DFA).
* @param[in] property Property of the automaton to minimize.
* - AutomatonProperty::Trimmed - Trim will not be performed.
* @param[in] aut NFA whose minimal version to compute.
* @param[in] params Optional parameters to control the minimization algorithm:
* - "algorithm": "hopcroft", "brzozowski" (Default: "brzozowski")
* @return Minimal deterministic automaton.
*/
Nfa minimize(const Nfa &aut,
const AutomatonType type,
const std::optional<AutomatonProperty> property = std::nullopt,
const ParameterMap& params = { { "algorithm", "brzozowski" } });
Nfa make_minimal_dfa(const Nfa &nfa, const ParameterMap& params = { { "algorithm", "brzozowski" } });

/**
* @brief Compute minimal deterministic automaton.
*
* @param[in] aut Automaton whose minimal version to compute.
* @param[in] aut DFA whose minimal version to compute. Trimming on the copy of the automaton
* will be performed if the automaton is not already trimmed.
* @param[in] params Optional parameters to control the minimization algorithm:
* - "algorithm": "hopcroft", "brzozowski" (Default: "brzozowski")
* - "algorithm": "hopcroft", "brzozowski" (Default: "hopcroft")
* @return Minimal deterministic automaton.
*/
Nfa minimize(const Nfa &aut, const ParameterMap& params = { { "algorithm", "brzozowski" } });
Nfa minimize(const Nfa &dfa, const ParameterMap& params = { { "algorithm", "hopcroft" } });

/**
* @brief Determinize automaton.
Expand Down
4 changes: 3 additions & 1 deletion include/mata/nfa/plumbing.hh
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ inline void complement(
{ "minimize", "false"}}) { *result = complement(aut, alphabet, params);
}

inline void minimize(Nfa* res, const Nfa &aut) { *res = minimize(aut); }
inline void minimize(Nfa* res, const Nfa &dfa, const ParameterMap& params = {{ "algorithm", "hopcroft" }}) { *res = minimize(dfa, params); }

inline void make_minimal_dfa(Nfa* res, const Nfa &nfa, const ParameterMap& params = {{ "algorithm", "brzozowski" }}) { *res = make_minimal_dfa(nfa, params); }

inline void determinize(Nfa* result, const Nfa& aut, std::unordered_map<StateSet, State> *subset_map = nullptr) {
*result = determinize(aut, subset_map);
Expand Down
36 changes: 9 additions & 27 deletions src/nfa/operations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ Nfa mata::nfa::algorithms::minimize_brzozowski(const Nfa& aut) {
return determinize(revert(determinize(revert(aut))));
}

Nfa mata::nfa::minimize_nfa(const Nfa& aut, const ParameterMap& params) {
Nfa mata::nfa::make_minimal_dfa(const Nfa& nfa, const ParameterMap& params) {
if (!haskey(params, "algorithm")) {
throw std::runtime_error(std::to_string(__func__) +
" requires setting the \"algorithm\" key in the \"params\" argument; "
Expand All @@ -943,12 +943,10 @@ Nfa mata::nfa::minimize_nfa(const Nfa& aut, const ParameterMap& params) {
" received an unknown value for the \"algorithm\" key: " + str_algo);
}

return algo(aut);
return algo(nfa);
}

Nfa mata::nfa::minimize_dfa(const Nfa &aut,
const std::optional<AutomatonProperty> property,
const ParameterMap& params)
Nfa mata::nfa::minimize(const Nfa &dfa, const ParameterMap& params)
{
if (!haskey(params, "algorithm")) {
throw std::runtime_error(std::to_string(__func__) +
Expand All @@ -969,28 +967,12 @@ Nfa mata::nfa::minimize_dfa(const Nfa &aut,
}

// Hopcroft algorithm does not work with non-trimmed automata.
if (str_algo == "hopcroft" && property != AutomatonProperty::Trimmed) {
return algo(Nfa(aut).trim());
const BoolVector is_used = dfa.get_useful_states();
bool is_trimmed = std::all_of(is_used.begin(), is_used.end(), [](bool b) { return b; });
if (str_algo == "hopcroft" && !is_trimmed) {
return algo(Nfa(dfa).trim());
}
return algo(aut);
}

Nfa mata::nfa::minimize(const Nfa &aut,
const AutomatonType type,
const std::optional<AutomatonProperty> property,
const ParameterMap& params)
{
if (type == AutomatonType::Dfa) {
return minimize_dfa(aut, property, params);
}
return minimize_nfa(aut, params);
}

Nfa mata::nfa::minimize(
const Nfa& aut,
const ParameterMap& params)
{
return minimize(aut, AutomatonType::Nfa, std::nullopt, params);
return algo(dfa);
}

// Anonymous namespace for the Hopcroft minimization algorithm.
Expand Down Expand Up @@ -1338,7 +1320,7 @@ Nfa mata::nfa::algorithms::minimize_hopcroft(const Nfa& dfa_trimmed) {
for (const SymbolPost &symbol_post : dfa_trimmed.delta[q]) {
assert(symbol_post.targets.size() == 1);
const State target = brp.set_idx[*symbol_post.targets.begin()];
mut_state_post.push_back(SymbolPost{ symbol_post.symbol, StateSet{ target } });
mut_state_post.emplace_back(SymbolPost{ symbol_post.symbol, StateSet{ target } });
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests-integration/src/test-unary-op.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) {

// minimization test
Nfa aut_min(aut);
aut_min = mata::nfa::minimize(aut_min);
aut_min = mata::nfa::make_minimal_dfa(aut_min);
std::cout << "minimize:" << (mata::nfa::are_equivalent(aut, aut_min) ? "ok" : "fail") << std::endl;

return EXIT_SUCCESS;
Expand Down
6 changes: 3 additions & 3 deletions tests-integration/src/unary-operations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ int main(int argc, char *argv[]) {
TIME_END(reduce);

Nfa minimized_aut;
TIME_BEGIN(minimize);
TIME_BEGIN(make_minimal_dfa);
// > START OF PROFILED CODE
// Only minimize and its callees will be measured
mata::nfa::plumbing::minimize(&minimized_aut, aut);
mata::nfa::plumbing::make_minimal_dfa(&minimized_aut, aut);
// > END OF PROFILED CODE
TIME_END(minimize);
TIME_END(make_minimal_dfa);

Nfa det_aut;
TIME_BEGIN(determinize);
Expand Down
2 changes: 1 addition & 1 deletion tests/nfa/nfa-plumbing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ TEST_CASE("Mata::nfa::Plumbing") {

SECTION("Mata::nfa::Plumbing::minimize") {
FILL_WITH_AUT_A(lhs);
mata::nfa::plumbing::minimize(&result, lhs);
mata::nfa::plumbing::make_minimal_dfa(&result, lhs);
CHECK(!result.is_lang_empty());
}

Expand Down
2 changes: 1 addition & 1 deletion tests/nfa/nfa.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1017,7 +1017,7 @@ TEST_CASE("mata::nfa::minimize() for profiling", "[.profiling],[minimize]") {
aut.delta.add(3, 110, 3);
aut.delta.add(3, 111, 3);
aut.delta.add(3, 114, 3);
minimize(&result, aut);
make_minimal_dfa(&result, aut);
}

TEST_CASE("mata::nfa::construct() correct calls")
Expand Down

0 comments on commit 52222c3

Please sign in to comment.