From 7f3c9b9e29519f78694a8004d55d1793f0a35276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Wed, 6 Sep 2023 07:46:52 +0200 Subject: [PATCH 01/23] Move 'add_symbols_to()' to 'Delta' from 'Nfa' --- include/mata/nfa/delta.hh | 7 +++++++ include/mata/nfa/nfa.hh | 7 ------- src/nfa/delta.cc | 10 ++++++++++ src/nfa/nfa.cc | 10 ---------- tests/nfa/delta.cc | 24 ++++++++++++++++++++++++ 5 files changed, 41 insertions(+), 17 deletions(-) diff --git a/include/mata/nfa/delta.hh b/include/mata/nfa/delta.hh index 1c9349ba3..0036bd095 100644 --- a/include/mata/nfa/delta.hh +++ b/include/mata/nfa/delta.hh @@ -441,6 +441,13 @@ public: * @return An iterator to @c SymbolPost with epsilon symbol. End iterator when there are no epsilon transitions. */ static StatePost::const_iterator epsilon_symbol_posts(const StatePost& state_post, Symbol epsilon = EPSILON); + + /** + * @brief Expand @p target_alphabet by symbols from this delta. + * + * The value of the already existing symbols will NOT be overwritten. + */ + void add_symbols_to(OnTheFlyAlphabet& target_alphabet) const; private: std::vector state_posts_; }; // class Delta. diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index d3bdab7c3..94746f75c 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -289,13 +289,6 @@ public: // TODO: Relict from VATA. What to do with inclusion/ universality/ this post function? Revise all of them. StateSet post(const StateSet& states, const Symbol& symbol) const; - - /** - * @brief Expand alphabet by symbols from this automaton to given alphabet - * - * The value of the already existing symbols will NOT be overwritten. - */ - void add_symbols_to(OnTheFlyAlphabet& target_alphabet) const; }; // struct Nfa. /** diff --git a/src/nfa/delta.cc b/src/nfa/delta.cc index b29c7111a..a592aab6d 100644 --- a/src/nfa/delta.cc +++ b/src/nfa/delta.cc @@ -512,3 +512,13 @@ Delta::Transitions::const_iterator Delta::Transitions::end() const { return cons StatePost::Moves::Moves( const StatePost& state_post, StatePost::const_iterator symbol_post_it, StatePost::const_iterator symbol_post_end) : state_post_{ &state_post }, symbol_post_it_{ symbol_post_it }, symbol_post_end_{ symbol_post_end } {} + +void Delta::add_symbols_to(OnTheFlyAlphabet& target_alphabet) const { + size_t aut_num_of_states{ num_of_states() }; + for (mata::nfa::State state{ 0 }; state < aut_num_of_states; ++state) { + for (const SymbolPost& move: state_post(state)) { + target_alphabet.update_next_symbol_value(move.symbol); + target_alphabet.try_add_new_symbol(std::to_string(move.symbol), move.symbol); + } + } +} diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index e1c24b5c0..708a2a36c 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -590,16 +590,6 @@ void Nfa::unify_final() { final.insert(new_final_state); } -void Nfa::add_symbols_to(OnTheFlyAlphabet& target_alphabet) const { - size_t aut_num_of_states{size() }; - for (mata::nfa::State state{ 0 }; state < aut_num_of_states; ++state) { - for (const SymbolPost& move: delta[state]) { - target_alphabet.update_next_symbol_value(move.symbol); - target_alphabet.try_add_new_symbol(std::to_string(move.symbol), move.symbol); - } - } -} - Nfa& Nfa::operator=(Nfa&& other) noexcept { if (this != &other) { delta = std::move(other.delta); diff --git a/tests/nfa/delta.cc b/tests/nfa/delta.cc index 8b55b9a40..27a87393c 100644 --- a/tests/nfa/delta.cc +++ b/tests/nfa/delta.cc @@ -435,3 +435,27 @@ TEST_CASE("mata::nfa::Delta::operator==()") { delta.add(0, 0, 3); CHECK(delta == delta2); } + +TEST_CASE("mata::nfa::Delta::add_symbols_to()") { + mata::OnTheFlyAlphabet empty_alphabet{}; + mata::OnTheFlyAlphabet alphabet{}; + Delta delta{}; + delta.add_symbols_to(alphabet); + CHECK(alphabet.get_symbol_map().empty()); + delta.add(0, 0, 0); + delta.add_symbols_to(alphabet); + CHECK(alphabet.get_symbol_map().size() == 1); + delta.add(0, 0, 0); + delta.add_symbols_to(alphabet); + CHECK(alphabet.get_symbol_map().size() == 1); + delta.add(0, 1, 0); + delta.add_symbols_to(alphabet); + CHECK(alphabet.get_symbol_map().size() == 2); + delta.add(0, 2, 0); + delta.add(0, 3, 0); + delta.add_symbols_to(alphabet); + CHECK(alphabet.get_symbol_map().size() == 4); + CHECK(alphabet.get_symbol_map() == std::unordered_map{ + { "0", 0 }, { "1", 1 }, { "2", 2 }, { "3", 3 } + }); +} From e593a5e1ffcdd37e6f08c0dc098de24633ecbb8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Wed, 6 Sep 2023 07:50:00 +0200 Subject: [PATCH 02/23] Remove clearing transitions as deprecated and replaced by 'Delta::clear()' --- include/mata/nfa/nfa.hh | 5 ----- src/nfa/nfa.cc | 7 ------- 2 files changed, 12 deletions(-) diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 94746f75c..3313341b3 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -103,11 +103,6 @@ public: Nfa& operator=(const Nfa& other) = default; Nfa& operator=(Nfa&& other) noexcept; - /** - * Clear transitions but keep the automata states. - */ - void clear_transitions(); - /** * Add a new (fresh) state to the automaton. * @return The newly created state. diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index 708a2a36c..63eb267a3 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -602,13 +602,6 @@ Nfa& Nfa::operator=(Nfa&& other) noexcept { return *this; } -void Nfa::clear_transitions() { - const size_t delta_size = delta.num_of_states(); - for (size_t i = 0; i < delta_size; ++i) { - delta.mutable_state_post(i) = StatePost(); - } -} - State Nfa::add_state() { const size_t num_of_states{ size() }; delta.increase_size(num_of_states + 1); From d9a2ede8bd9a8c1abf9ffa8d9556b18bc07c9e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Wed, 6 Sep 2023 08:24:04 +0200 Subject: [PATCH 03/23] Move 'get_used_symbols()' to 'Delta' --- bindings/python/libmata/nfa/nfa.pxd | 2 +- bindings/python/libmata/nfa/nfa.pyx | 2 +- include/mata/nfa/delta.hh | 17 +++- include/mata/nfa/nfa.hh | 14 --- src/nfa/delta.cc | 146 +++++++++++++++++++++++++++ src/nfa/nfa.cc | 151 ---------------------------- src/nfa/operations.cc | 11 +- tests/nfa/nfa-profiling.cc | 10 +- tests/strings/nfa-noodlification.cc | 10 +- 9 files changed, 178 insertions(+), 185 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 4b7f2c891..8c5884148 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -84,6 +84,7 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": COrdVector[CSymbolPost].const_iterator epsilon_symbol_posts(CStatePost& post, Symbol epsilon) size_t num_of_transitions() CTransitions transitions() + COrdVector[Symbol] get_used_symbols() cdef cppclass CRun "mata::nfa::Run": # Public Attributes @@ -152,7 +153,6 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": void clear_final() void unify_initial() void unify_final() - COrdVector[Symbol] get_used_symbols() bool is_state(State) StateSet post(StateSet&, Symbol) State add_state() diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index 5f2e4fecb..c13f89f84 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -687,7 +687,7 @@ cdef class Nfa: :return: Set of symbols. """ - cdef COrdVector[Symbol] symbols = self.thisptr.get().get_used_symbols() + cdef COrdVector[Symbol] symbols = self.thisptr.get().delta.get_used_symbols() return {s for s in symbols} diff --git a/include/mata/nfa/delta.hh b/include/mata/nfa/delta.hh index 0036bd095..ae3b907eb 100644 --- a/include/mata/nfa/delta.hh +++ b/include/mata/nfa/delta.hh @@ -3,9 +3,10 @@ #ifndef MATA_DELTA_HH #define MATA_DELTA_HH +#include "mata/utils/sparse-set.hh" +#include "mata/utils/synchronized-iterator.hh" #include "mata/alphabet.hh" #include "mata/nfa/types.hh" -#include "mata/utils/synchronized-iterator.hh" #include @@ -448,6 +449,20 @@ public: * The value of the already existing symbols will NOT be overwritten. */ void add_symbols_to(OnTheFlyAlphabet& target_alphabet) const; + + /** + * @brief Get the set of symbols used on the transitions in the automaton. + * + * Does not necessarily have to equal the set of symbols in the alphabet used by the automaton. + * @return Set of symbols used on the transitions. + */ + utils::OrdVector get_used_symbols() const; + + utils::OrdVector get_used_symbols_vec() const; + std::set get_used_symbols_set() const; + utils::SparseSet get_used_symbols_sps() const; + std::vector get_used_symbols_bv() const; + BoolVector get_used_symbols_chv() const; private: std::vector state_posts_; }; // class Delta. diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 3313341b3..8017a054e 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -151,20 +151,6 @@ public: */ bool is_identical(const Nfa & aut); - /** - * @brief Get the set of symbols used on the transitions in the automaton. - * - * Does not necessarily have to equal the set of symbols in the alphabet used by the automaton. - * @return Set of symbols used on the transitions. - * TODO: this should be a method of Delta? - */ - utils::OrdVector get_used_symbols() const; - - mata::utils::OrdVector get_used_symbols_vec() const; - std::set get_used_symbols_set() const; - mata::utils::SparseSet get_used_symbols_sps() const; - std::vector get_used_symbols_bv() const; - BoolVector get_used_symbols_chv() const; /** * @brief Get the maximum non-e used symbol. diff --git a/src/nfa/delta.cc b/src/nfa/delta.cc index a592aab6d..6095ae6f3 100644 --- a/src/nfa/delta.cc +++ b/src/nfa/delta.cc @@ -522,3 +522,149 @@ void Delta::add_symbols_to(OnTheFlyAlphabet& target_alphabet) const { } } } + +OrdVector Delta::get_used_symbols() const { + //TODO: look at the variants in profiling (there are tests in tests-nfa-profiling.cc), + // for instance figure out why NumberPredicate and OrdVedctor are slow, + // try also with _STATIC_DATA_STRUCTURES_, it changes things. + + //below are different variant, with different data structures for accumulating symbols, + //that then must be converted to an OrdVector + //measured are times with "mata::nfa::get_used_symbols speed, harder", "[.profiling]" now on line 104 of nfa-profiling.cc + + //WITH VECTOR (4.434 s) + //return get_used_symbols_vec(); + + //WITH SET (26.5 s) + //auto from_set = get_used_symbols_set(); + //return utils::OrdVector (from_set .begin(),from_set.end()); + + //WITH NUMBER PREDICATE (4.857s) (NP removed) + //return utils::OrdVector(get_used_symbols_np().get_elements()); + + //WITH SPARSE SET (haven't tried) + //return utils::OrdVector(get_used_symbols_sps()); + + //WITH BOOL VECTOR (error !!!!!!!): + //return utils::OrdVector(utils::NumberPredicate(get_used_symbols_bv())); + + //WITH BOOL VECTOR (1.9s): + std::vector bv{ get_used_symbols_bv() }; + utils::OrdVector ov{}; + const size_t bv_size{ bv.size() }; + for (Symbol i{ 0 }; i < bv_size; ++i) { if (bv[i]) { ov.push_back(i); } } + return ov; + + ///WITH BOOL VECTOR, DIFFERENT VARIANT? (1.9s): + //std::vector bv = get_used_symbols_bv(); + //std::vector v(std::count(bv.begin(), bv.end(), true)); + //return utils::OrdVector(v); + + //WITH CHAR VECTOR (should be the fastest, haven't tried in this branch): + //BEWARE: failing in one noodlificatoin test ("Simple automata -- epsilon result") ... strange + //BoolVector chv = get_used_symbols_chv(); + //utils::OrdVector ov; + //for(Symbol i = 0;i Delta::get_used_symbols_vec() const { +#ifdef _STATIC_STRUCTURES_ + static std::vector symbols{}; + symbols.clear(); +#else + std::vector symbols{}; +#endif + for (const StatePost& state_post: state_posts_) { + for (const SymbolPost & symbol_post: state_post) { + utils::reserve_on_insert(symbols); + symbols.push_back(symbol_post.symbol); + } + } + utils::OrdVector sorted_symbols(symbols); + return sorted_symbols; +} + +// returns symbols appearing in Delta, inserts to a std::set +std::set Delta::get_used_symbols_set() const { + //static should prevent reallocation, seems to speed things up a little +#ifdef _STATIC_STRUCTURES_ + static std::set symbols; + symbols.clear(); +#else + static std::set symbols{}; +#endif + for (const StatePost& state_post: state_posts_) { + for (const SymbolPost& symbol_post: state_post) { + symbols.insert(symbol_post.symbol); + } + } + return symbols; + //utils::OrdVector sorted_symbols(symbols.begin(),symbols.end()); + //return sorted_symbols; +} + +// returns symbols appearing in Delta, adds to NumberPredicate, +// Seems to be the fastest option, but could have problems with large maximum symbols +mata::utils::SparseSet Delta::get_used_symbols_sps() const { +#ifdef _STATIC_STRUCTURES_ + //static seems to speed things up a little + static utils::SparseSet symbols(64,false); + symbols.clear(); +#else + utils::SparseSet symbols(64); +#endif + //symbols.dont_track_elements(); + for (const StatePost& state_post: state_posts_) { + for (const SymbolPost & symbol_post: state_post) { + symbols.insert(symbol_post.symbol); + } + } + //TODO: is it necessary to return ordered vector? Would the number predicate suffice? + return symbols; +} + +// returns symbols appearing in Delta, adds to NumberPredicate, +// Seems to be the fastest option, but could have problems with large maximum symbols +std::vector Delta::get_used_symbols_bv() const { +#ifdef _STATIC_STRUCTURES_ + //static seems to speed things up a little + static std::vector symbols(64,false); + symbols.clear(); +#else + std::vector symbols(64,false); +#endif + //symbols.dont_track_elements(); + for (const StatePost& state_post: state_posts_) { + for (const SymbolPost& symbol_post: state_post) { + reserve_on_insert(symbols,symbol_post.symbol); + symbols[symbol_post.symbol] = true; + } + } + //TODO: is it neccessary toreturn ordered vector? Would the number predicate suffice? + return symbols; +} + +mata::BoolVector Delta::get_used_symbols_chv() const { +#ifdef _STATIC_STRUCTURES_ + //static seems to speed things up a little + static BoolVector symbols(64,false); + symbols.clear(); +#else + BoolVector symbols(64,false); +#endif + //symbols.dont_track_elements(); + for (const StatePost& state_post: state_posts_) { + for (const SymbolPost& symbol_post: state_post) { + reserve_on_insert(symbols,symbol_post.symbol); + symbols[symbol_post.symbol] = true; + } + } + //TODO: is it necessary to return ordered vector? Would the number predicate suffice? + return symbols; +} diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index 63eb267a3..ef8c93c9b 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -444,108 +444,6 @@ StateSet Nfa::post(const StateSet& states, const Symbol& symbol) const { return res; } -// Other versions, maybe an interesting experiment with speed of data structures. -// Returns symbols appearing in Delta, pushes back to vector and then sorts -mata::utils::OrdVector Nfa::get_used_symbols_vec() const { -#ifdef _STATIC_STRUCTURES_ - static std::vector symbols{}; - symbols.clear(); -#else - std::vector symbols{}; -#endif - for (State q = 0; q< delta.num_of_states(); ++q) { - const StatePost & post = delta[q]; - for (const SymbolPost & move: post) { - utils::reserve_on_insert(symbols); - symbols.push_back(move.symbol); - } - } - utils::OrdVector sorted_symbols(symbols); - return sorted_symbols; -} - -// returns symbols appearing in Delta, inserts to a std::set -std::set Nfa::get_used_symbols_set() const { - //static should prevent reallocation, seems to speed things up a little -#ifdef _STATIC_STRUCTURES_ - static std::set symbols; - symbols.clear(); -#else - static std::set symbols{}; -#endif - for (State q = 0; q< delta.num_of_states(); ++q) { - const StatePost & post = delta[q]; - for (const SymbolPost & move: post) { - symbols.insert(move.symbol); - } - } - return symbols; - //utils::OrdVector sorted_symbols(symbols.begin(),symbols.end()); - //return sorted_symbols; -} - -// returns symbols appearing in Delta, adds to NumberPredicate, -// Seems to be the fastest option, but could have problems with large maximum symbols -mata::utils::SparseSet Nfa::get_used_symbols_sps() const { -#ifdef _STATIC_STRUCTURES_ - //static seems to speed things up a little - static utils::SparseSet symbols(64,false); - symbols.clear(); -#else - utils::SparseSet symbols(64); -#endif - //symbols.dont_track_elements(); - for (State q = 0; q< delta.num_of_states(); ++q) { - const StatePost & post = delta[q]; - for (const SymbolPost & move: post) { - symbols.insert(move.symbol); - } - } - //TODO: is it necessary to return ordered vector? Would the number predicate suffice? - return symbols; -} - -// returns symbols appearing in Delta, adds to NumberPredicate, -// Seems to be the fastest option, but could have problems with large maximum symbols -std::vector Nfa::get_used_symbols_bv() const { -#ifdef _STATIC_STRUCTURES_ - //static seems to speed things up a little - static std::vector symbols(64,false); - symbols.clear(); -#else - std::vector symbols(64,false); -#endif - //symbols.dont_track_elements(); - for (State q = 0; q< delta.num_of_states(); ++q) { - const StatePost & post = delta[q]; - for (const SymbolPost & move: post) { - reserve_on_insert(symbols,move.symbol); - symbols[move.symbol]=true; - } - } - //TODO: is it neccessary toreturn ordered vector? Would the number predicate suffice? - return symbols; -} - -BoolVector Nfa::get_used_symbols_chv() const { -#ifdef _STATIC_STRUCTURES_ - //static seems to speed things up a little - static BoolVector symbols(64,false); - symbols.clear(); -#else - BoolVector symbols(64,false); -#endif - //symbols.dont_track_elements(); - for (State q = 0; q< delta.num_of_states(); ++q) { - const StatePost & post = delta[q]; - for (const SymbolPost & move: post) { - reserve_on_insert(symbols,move.symbol); - symbols[move.symbol]=true; - } - } - //TODO: is it necessary to return ordered vector? Would the number predicate suffice? - return symbols; -} // returns max non-e symbol in Delta Symbol Nfa::get_max_symbol() const { @@ -639,52 +537,3 @@ bool Nfa::is_identical(const Nfa& aut) { return delta == aut.delta; } -OrdVector Nfa::get_used_symbols() const { - //TODO: look at the variants in profiling (there are tests in tests-nfa-profiling.cc), - // for instance figure out why NumberPredicate and OrdVedctor are slow, - // try also with _STATIC_DATA_STRUCTURES_, it changes things. - - //below are different variant, with different data structures for accumulating symbols, - //that then must be converted to an OrdVector - //measured are times with "mata::nfa::get_used_symbols speed, harder", "[.profiling]" now on line 104 of nfa-profiling.cc - - //WITH VECTOR (4.434 s) - //return get_used_symbols_vec(); - - //WITH SET (26.5 s) - //auto from_set = get_used_symbols_set(); - //return utils::OrdVector (from_set .begin(),from_set.end()); - - //WITH NUMBER PREDICATE (4.857s) (NP removed) - //return utils::OrdVector(get_used_symbols_np().get_elements()); - - //WITH SPARSE SET (haven't tried) - //return utils::OrdVector(get_used_symbols_sps()); - - //WITH BOOL VECTOR (error !!!!!!!): - //return utils::OrdVector(utils::NumberPredicate(get_used_symbols_bv())); - - //WITH BOOL VECTOR (1.9s): - std::vector bv = get_used_symbols_bv(); - utils::OrdVector ov; - for(Symbol i = 0;i bv = get_used_symbols_bv(); - //std::vector v(std::count(bv.begin(), bv.end(), true)); - //return utils::OrdVector(v); - - //WITH CHAR VECTOR (should be the fastest, haven't tried in this branch): - //BEWARE: failing in one noodlificatoin test ("Simple automata -- epsilon result") ... strange - //BoolVector chv = get_used_symbols_chv(); - //utils::OrdVector ov; - //for(Symbol i = 0;i symbols = aut.get_used_symbols(); - if (symbols.empty()) - return result; - if (symbols.back() == EPSILON) - symbols.pop_back(); + // Compute non-epsilon symbols. + OrdVector symbols = aut.delta.get_used_symbols(); + if (symbols.empty()) { return result; } + if (symbols.back() == EPSILON) { symbols.pop_back(); } // size of the "used alphabet", i.e. max symbol+1 or 0 Symbol alphasize = (symbols.empty()) ? 0 : (symbols.back()+1); diff --git a/tests/nfa/nfa-profiling.cc b/tests/nfa/nfa-profiling.cc index b270e2331..232603e0b 100644 --- a/tests/nfa/nfa-profiling.cc +++ b/tests/nfa/nfa-profiling.cc @@ -85,7 +85,7 @@ TEST_CASE("mata::nfa::get_used_symbols speed, harder", "[.profiling]") { Nfa A; create_nfa(&A, "((.*){10})*"); for (int i = 0; i < 2000000; i++) { - A.get_used_symbols(); + A.delta.get_used_symbols(); } } @@ -93,7 +93,7 @@ TEST_CASE("mata::nfa::get_used_symbols_bv speed, harder", "[.profiling]") { Nfa A; create_nfa(&A, "((.*){10})*"); for (int i = 0; i < 2000000; i++) { - A.get_used_symbols_bv(); + A.delta.get_used_symbols_bv(); } } @@ -101,7 +101,7 @@ TEST_CASE("mata::nfa::get_used_symbols_vec speed, harder", "[.profiling]") { Nfa A; create_nfa(&A, "((.*){10})*"); for (int i = 0; i < 2000000; i++) { - A.get_used_symbols_vec(); + A.delta.get_used_symbols_vec(); } } @@ -109,7 +109,7 @@ TEST_CASE("mata::nfa::get_used_symbols_set speed, harder", "[.profiling]") { Nfa A; create_nfa(&A, "((.*){10})*"); for (int i = 0; i < 2000000; i++) { - A.get_used_symbols_set(); + A.delta.get_used_symbols_set(); } } @@ -117,7 +117,7 @@ TEST_CASE("mata::nfa::get_used_symbols_sps speed, harder", "[.profiling]") { Nfa A; create_nfa(&A, "((.*){10})*"); for (int i = 0; i < 2000000; i++) { - A.get_used_symbols_sps(); + A.delta.get_used_symbols_sps(); } } diff --git a/tests/strings/nfa-noodlification.cc b/tests/strings/nfa-noodlification.cc index 7c467c20b..c974bafb9 100644 --- a/tests/strings/nfa-noodlification.cc +++ b/tests/strings/nfa-noodlification.cc @@ -377,7 +377,7 @@ TEST_CASE("mata::nfa::SegNfa::noodlify_for_equation() both sides") { for(size_t j = 0; j < noodles[i].size(); j++) { CHECK(noodles[i][j].second == res[i][j].second); CHECK(are_equivalent(*noodles[i][j].first.get(), res[i][j].first, nullptr)); - auto used_symbols{ noodles[i][j].first->get_used_symbols() }; + auto used_symbols{ noodles[i][j].first->delta.get_used_symbols() }; CHECK(used_symbols.find(EPSILON) == used_symbols.end()); } } @@ -404,7 +404,7 @@ TEST_CASE("mata::nfa::SegNfa::noodlify_for_equation() both sides") { for(size_t j = 0; j < noodles[i].size(); j++) { CHECK(noodles[i][j].second == res[i][j].second); CHECK(are_equivalent(*noodles[i][j].first.get(), res[i][j].first, nullptr)); - auto used_symbols{ noodles[i][j].first->get_used_symbols() }; + auto used_symbols{ noodles[i][j].first->delta.get_used_symbols() }; CHECK(used_symbols.find(EPSILON) == used_symbols.end()); } } @@ -426,7 +426,7 @@ TEST_CASE("mata::nfa::SegNfa::noodlify_for_equation() both sides") { for(size_t j = 0; j < noodles[i].size(); j++) { CHECK(noodles[i][j].second == res[i][j].second); CHECK(are_equivalent(*noodles[i][j].first.get(), res[i][j].first, nullptr)); - auto used_symbols{ noodles[i][j].first->get_used_symbols() }; + auto used_symbols{ noodles[i][j].first->delta.get_used_symbols() }; CHECK(used_symbols.find(EPSILON) == used_symbols.end()); } } @@ -451,7 +451,7 @@ TEST_CASE("mata::nfa::SegNfa::noodlify_for_equation() both sides") { for(size_t j = 0; j < noodles[i].size(); j++) { CHECK(noodles[i][j].second == res[i][j].second); CHECK(are_equivalent(*noodles[i][j].first.get(), res[i][j].first, nullptr)); - auto used_symbols{ noodles[i][j].first->get_used_symbols() }; + auto used_symbols{ noodles[i][j].first->delta.get_used_symbols() }; CHECK(used_symbols.find(EPSILON) == used_symbols.end()); } } @@ -475,7 +475,7 @@ TEST_CASE("mata::nfa::SegNfa::noodlify_for_equation() both sides") { for(size_t j = 0; j < noodles[i].size(); j++) { CHECK(noodles[i][j].second == res[i][j].second); CHECK(are_equivalent(*noodles[i][j].first.get(), res[i][j].first, nullptr)); - auto used_symbols{ noodles[i][j].first->get_used_symbols() }; + auto used_symbols{ noodles[i][j].first->delta.get_used_symbols() }; CHECK(used_symbols.find(EPSILON) == used_symbols.end()); } } From 6267ff978013d05ac6cc66891b340065c2c5b66f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Wed, 6 Sep 2023 08:24:27 +0200 Subject: [PATCH 04/23] Move 'get_max_symbol' to 'Delta' --- include/mata/nfa/delta.hh | 5 +++++ include/mata/nfa/nfa.hh | 6 ------ src/nfa/delta.cc | 10 ++++++++++ src/nfa/nfa.cc | 14 -------------- src/nfa/operations.cc | 4 ++-- 5 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/mata/nfa/delta.hh b/include/mata/nfa/delta.hh index ae3b907eb..7285b618e 100644 --- a/include/mata/nfa/delta.hh +++ b/include/mata/nfa/delta.hh @@ -463,6 +463,11 @@ public: utils::SparseSet get_used_symbols_sps() const; std::vector get_used_symbols_bv() const; BoolVector get_used_symbols_chv() const; + + /** + * @brief Get the maximum non-epsilon used symbol. + */ + Symbol get_max_symbol() const; private: std::vector state_posts_; }; // class Delta. diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 8017a054e..fce6c9b67 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -151,12 +151,6 @@ public: */ bool is_identical(const Nfa & aut); - - /** - * @brief Get the maximum non-e used symbol. - * TODO: this should be a method of Delta? - */ - Symbol get_max_symbol() const; /** * @brief Get set of reachable states. * diff --git a/src/nfa/delta.cc b/src/nfa/delta.cc index 6095ae6f3..c5bc6b1aa 100644 --- a/src/nfa/delta.cc +++ b/src/nfa/delta.cc @@ -668,3 +668,13 @@ mata::BoolVector Delta::get_used_symbols_chv() const { //TODO: is it necessary to return ordered vector? Would the number predicate suffice? return symbols; } + +Symbol Delta::get_max_symbol() const { + Symbol max{ 0 }; + for (const StatePost& state_post: state_posts_) { + for (const SymbolPost& symbol_post: state_post) { + if (symbol_post.symbol > max) { max = symbol_post.symbol; } + } + } + return max; +} diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index ef8c93c9b..a85d98554 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -444,20 +444,6 @@ StateSet Nfa::post(const StateSet& states, const Symbol& symbol) const { return res; } - -// returns max non-e symbol in Delta -Symbol Nfa::get_max_symbol() const { - Symbol max = 0; - for (State q = 0; q< delta.num_of_states(); ++q) { - const StatePost & post = delta[q]; - for (const SymbolPost & move: post) { - if (move.symbol > max) - max = move.symbol; - } - } - return max; -} - void Nfa::unify_initial() { if (initial.empty() || initial.size() == 1) { return; } const State new_initial_state{add_state() }; diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 0fd8f1c5b..4059ce847 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -38,8 +38,8 @@ using StateBoolArray = std::vector; ///< Bool array for states in the auto namespace { Simlib::Util::BinaryRelation compute_fw_direct_simulation(const Nfa& aut) { - Symbol maxSymbol{ aut.get_max_symbol() }; - const size_t state_num = aut.size(); + Symbol maxSymbol{ aut.delta.get_max_symbol() }; + const size_t state_num{ aut.num_of_states() }; Simlib::ExplicitLTS LTSforSimulation(state_num); for (const Transition& transition : aut.delta.transitions()) { From 7180fa8abb7a5839872144d846636c9a6295ed7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Wed, 6 Sep 2023 12:46:15 +0200 Subject: [PATCH 05/23] Use range for loops --- src/nfa/operations.cc | 4 +--- src/strings/nfa-noodlification.cc | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 4059ce847..d3639c673 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -398,9 +398,7 @@ Nfa mata::nfa::somewhat_simple_revert(const Nfa& aut) { for (State q = 0, states_num = result.delta.num_of_states(); q < states_num; ++q) { //Post & post = result.delta.get_mutable_post(q); //utils::sort_and_rmdupl(post); - for (auto m = result.delta.mutable_state_post(q).begin(); m != result.delta.mutable_state_post(q).end(); ++m) { - sort_and_rmdupl(m->targets); - } + for (SymbolPost& m: result.delta.mutable_state_post(q)) { sort_and_rmdupl(m.targets); } } return result; diff --git a/src/strings/nfa-noodlification.cc b/src/strings/nfa-noodlification.cc index e24116ab0..91a29f141 100644 --- a/src/strings/nfa-noodlification.cc +++ b/src/strings/nfa-noodlification.cc @@ -407,7 +407,7 @@ std::vector seg_nfa::noodlify_for_equation( seg_nfa::VisitedEpsilonsCounterVector seg_nfa::process_eps_map(const VisitedEpsilonsCounterMap& eps_cnt) { VisitedEpsilonsCounterVector ret; - for(auto it = eps_cnt.rbegin(); it != eps_cnt.rend(); it++) { + for (auto it = eps_cnt.rbegin(); it != eps_cnt.rend(); ++it) { ret.push_back(it->second); } return ret; From 00983530f134345654d6daedac54d8a0f88e8ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Wed, 6 Sep 2023 13:00:05 +0200 Subject: [PATCH 06/23] Use emplace_back() where possible --- src/nfa/delta.cc | 2 +- src/strings/nfa-segmentation.cc | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/nfa/delta.cc b/src/nfa/delta.cc index c5bc6b1aa..f74f0fd73 100644 --- a/src/nfa/delta.cc +++ b/src/nfa/delta.cc @@ -187,7 +187,7 @@ bool Delta::empty() const { return true; } -Delta::Transitions::const_iterator::const_iterator(const Delta& delta): delta_{ &delta }, current_state_{ 0 } { +Delta::Transitions::const_iterator::const_iterator(const Delta& delta): delta_{ &delta } { const size_t post_size = delta_->num_of_states(); for (size_t i = 0; i < post_size; ++i) { if (!(*delta_)[i].empty()) { diff --git a/src/strings/nfa-segmentation.cc b/src/strings/nfa-segmentation.cc index f90aa634c..c2b2db2e9 100644 --- a/src/strings/nfa-segmentation.cc +++ b/src/strings/nfa-segmentation.cc @@ -45,13 +45,14 @@ void seg_nfa::Segmentation::handle_epsilon_transitions(const StateDepthTuple& st for (State target_state: move.targets) { - this->epsilon_depth_transitions[state_depth_pair.depth].push_back( - Transition{ state_depth_pair.state, move.symbol, target_state } + // TODO: Use vector indexed by depths instead of a map. + this->epsilon_depth_transitions[state_depth_pair.depth].emplace_back( + state_depth_pair.state, move.symbol, target_state ); - this->eps_depth_trans_map[state_depth_pair.depth][state_depth_pair.state].push_back( - Transition{ state_depth_pair.state, move.symbol, target_state } + this->eps_depth_trans_map[state_depth_pair.depth][state_depth_pair.state].emplace_back( + state_depth_pair.state, move.symbol, target_state ); - worklist.push_back(StateDepthTuple{ target_state, state_depth_pair.depth + 1, visited_eps_aux }); + worklist.push_back({ target_state, state_depth_pair.depth + 1, visited_eps_aux }); this->visited_eps[target_state] = visited_eps_aux; } } From 6f252371f1a6d5b126202a2287b0ce657262b05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 07:55:20 +0200 Subject: [PATCH 07/23] Rename 'Nfa::size()' to 'Nfa::num_of_states()' --- bindings/python/libmata/nfa/nfa.pxd | 2 +- bindings/python/libmata/nfa/nfa.pyx | 6 +-- bindings/python/libmata/nfa/strings.pyx | 2 +- bindings/python/libmata/plotting.pyx | 2 +- bindings/python/tests/test_nfa.py | 34 +++++++------- include/mata/nfa/nfa.hh | 12 ++--- src/nfa/complement.cc | 6 +-- src/nfa/concatenation.cc | 10 ++-- src/nfa/inclusion.cc | 2 +- src/nfa/nfa.cc | 14 +++--- src/nfa/operations.cc | 16 +++---- src/re2parser.cc | 4 +- src/strings/nfa-noodlification.cc | 14 +++--- src/strings/nfa-segmentation.cc | 2 +- src/strings/nfa-strings.cc | 4 +- tests/nfa/nfa-concatenation.cc | 38 +++++++-------- tests/nfa/nfa-intersection.cc | 2 +- tests/nfa/nfa-plumbing.cc | 4 +- tests/nfa/nfa.cc | 62 ++++++++++++------------- 19 files changed, 118 insertions(+), 118 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 8c5884148..c16587b95 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -167,7 +167,7 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": StateSet get_terminating_states() void remove_epsilon(Symbol) except + void clear() - size_t size() + size_t num_of_states() # Automata tests cdef bool c_is_deterministic "mata::nfa::is_deterministic" (CNfa&) diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index c13f89f84..cbf39cf32 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -390,11 +390,11 @@ cdef class Nfa: """Clears all of the internals in the automaton""" self.thisptr.get().clear() - def size(self) -> int: + def num_of_states(self) -> int: """Get the current number of states in the whole automaton. :return: The number of states. """ - return self.thisptr.get().size() + return self.thisptr.get().num_of_states() def iterate(self): """Iterates over all transitions @@ -844,7 +844,7 @@ def make_complete(Nfa lhs, State sink_state, alph.Alphabet alphabet): :param OnTheFlyAlphabet alphabet: alphabet of the """ if not lhs.thisptr.get().is_state(sink_state): - lhs.thisptr.get().add_state(lhs.size()) + lhs.thisptr.get().add_state(lhs.num_of_states()) mata_nfa.c_make_complete(lhs.thisptr.get(), dereference(alphabet.as_base()), sink_state) def revert(Nfa lhs): diff --git a/bindings/python/libmata/nfa/strings.pyx b/bindings/python/libmata/nfa/strings.pyx index 895b6bfea..2b222ea7f 100644 --- a/bindings/python/libmata/nfa/strings.pyx +++ b/bindings/python/libmata/nfa/strings.pyx @@ -47,7 +47,7 @@ cdef class Segmentation: segments = [] cdef vector[CNfa] c_segments = self.thisptr.get_segments() for c_segment in c_segments: - segment = mata_nfa.Nfa(c_segment.size()) + segment = mata_nfa.Nfa(c_segment.num_of_states()) (segment).thisptr.get().initial = c_segment.initial (segment).thisptr.get().final = c_segment.final (segment).thisptr.get().delta = c_segment.delta diff --git a/bindings/python/libmata/plotting.pyx b/bindings/python/libmata/plotting.pyx index 884bb40db..490849216 100644 --- a/bindings/python/libmata/plotting.pyx +++ b/bindings/python/libmata/plotting.pyx @@ -108,7 +108,7 @@ def plot_using_graphviz( ) else: # Only print reachable states - for state in range(0, aut.size()): + for state in range(0, aut.num_of_states()): # Helper node to simulate initial automaton _plot_state( aut, dot, state, diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index 818f4c07b..814baf498 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -16,7 +16,7 @@ def test_adding_states(): lhs = mata_nfa.Nfa(5) # Test adding states - assert lhs.size() == 5 + assert lhs.num_of_states() == 5 assert not lhs.has_initial_state(0) assert not lhs.has_final_state(0) lhs.make_initial_state(0) @@ -38,25 +38,25 @@ def test_adding_states(): assert lhs.has_final_state(0) rhs = mata_nfa.Nfa() - assert rhs.size() == 0 + assert rhs.num_of_states() == 0 state = rhs.add_new_state() assert state == 0 - assert rhs.size() == 1 + assert rhs.num_of_states() == 1 state = rhs.add_new_state() assert state == 1 - assert rhs.size() == 2 + assert rhs.num_of_states() == 2 rhs.add_state(9) - assert rhs.size() == 10 + assert rhs.num_of_states() == 10 for i in range(0, 10): assert rhs.is_state(i) - assert rhs.size() == 10 + assert rhs.num_of_states() == 10 rhs.clear() - assert rhs.size() == 0 + assert rhs.num_of_states() == 0 rhs.add_state(0) - assert rhs.size() == 1 + assert rhs.num_of_states() == 1 assert rhs.is_state(0) assert not rhs.is_state(1) @@ -64,7 +64,7 @@ def test_adding_states(): rhs.add_state(-10) rhs.add_state(11) - assert rhs.size() == 12 + assert rhs.num_of_states() == 12 assert rhs.is_state(11) assert not rhs.is_state(12) @@ -348,7 +348,7 @@ def test_concatenate(): result = mata_nfa.concatenate(lhs, rhs, True) assert result.has_initial_state(0) assert result.has_final_state(3) - assert result.size() == 4 + assert result.num_of_states() == 4 assert result.has_transition(0, ord('b'), 1) assert result.has_transition(1, mata_nfa.epsilon(), 2) assert result.has_transition(2, ord('a'), 3) @@ -356,7 +356,7 @@ def test_concatenate(): result, _, rhs_map = mata_nfa.concatenate_with_result_state_maps(lhs, rhs, True) assert result.has_initial_state(0) assert result.has_final_state(3) - assert result.size() == 4 + assert result.num_of_states() == 4 assert result.has_transition(0, ord('b'), 1) assert result.has_transition(1, mata_nfa.epsilon(), 2) assert result.has_transition(2, ord('a'), 3) @@ -478,7 +478,7 @@ def test_intersection_preserving_epsilon_transitions(): result, product_map = mata_nfa.intersection_with_product_map(a, b, True) # Check states. - assert result.size() == 13 + assert result.num_of_states() == 13 assert result.is_state(product_map[(0, 0)]) assert result.is_state(product_map[(1, 0)]) assert result.is_state(product_map[(1, 1)]) @@ -666,7 +666,7 @@ def test_trim(prepare_automaton_a): nfa.remove_final_state(2) # '2' is the new final state in the earlier trimmed automaton. nfa.trim() assert nfa.get_num_of_transitions() == 0 - assert nfa.size() == 0 + assert nfa.num_of_states() == 0 def test_get_one_letter_automaton(prepare_automaton_a): @@ -676,7 +676,7 @@ def test_get_one_letter_automaton(prepare_automaton_a): one_letter_automaton = nfa.get_one_letter_aut() - assert one_letter_automaton.size() == nfa.size() + assert one_letter_automaton.num_of_states() == nfa.num_of_states() assert one_letter_automaton.get_num_of_transitions() == 12 assert one_letter_automaton.has_transition(1, abstract_symbol, 10) assert one_letter_automaton.has_transition(10, abstract_symbol, 7) @@ -906,7 +906,7 @@ def test_reduce(): nfa.make_final_state(2) result, state_map = mata_nfa.reduce_with_state_map(nfa) assert result.get_num_of_transitions() == 0 - assert result.size() == 2 + assert result.num_of_states() == 2 assert result.has_initial_state(state_map[1]) assert result.has_final_state(state_map[2]) assert state_map[1] == state_map[0] @@ -914,7 +914,7 @@ def test_reduce(): result, state_map = mata_nfa.reduce_with_state_map(nfa.trim()) assert result.get_num_of_transitions() == 0 - assert result.size() == 0 + assert result.num_of_states() == 0 # Test the reduction of a bigger automaton. nfa.add_state(9) @@ -937,7 +937,7 @@ def test_reduce(): nfa.add_transition(0, ord('a'), 4) result, state_map = mata_nfa.reduce_with_state_map(nfa) - assert result.size() == 6 + assert result.num_of_states() == 6 assert result.has_initial_state(state_map[1]) assert result.has_initial_state(state_map[2]) assert result.has_final_state(state_map[9]) diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index fce6c9b67..166c64dc1 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -121,7 +121,7 @@ public: * This includes the initial and final states as well as states in the transition relation. * @return The number of states. */ - size_t size() const; + size_t num_of_states() const; /** * Unify initial states into a single new initial state. @@ -133,7 +133,7 @@ public: */ void unify_final(); - bool is_state(const State &state_to_check) const { return state_to_check < size(); } + bool is_state(const State &state_to_check) const { return state_to_check < num_of_states(); } /** * @brief Clear the underlying NFA to a blank NFA. @@ -373,7 +373,7 @@ Nfa concatenate(const Nfa& lhs, const Nfa& rhs, bool use_epsilon = false, /** * Make @c aut complete in place. * - * For each state 0,...,aut.size()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur + * For each state 0,...,aut.num_of_states()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur * on transitions from given state) to @p sink_state. If @p sink_state does not belong to the automaton, it is added to * it, but only in the case that some transition to @p sink_state was added. * In the case that @p aut does not contain any states, this function does nothing. @@ -388,7 +388,7 @@ bool make_complete(Nfa& aut, const Alphabet& alphabet, State sink_state); /** * Make @c aut complete in place. * - * For each state 0,...,aut.size()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur + * For each state 0,...,aut.num_of_states()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur * on transitions from given state) to @p sink_state. If @p sink_state does not belong to the automaton, it is added to * it, but only in the case that some transition to @p sink_state was added. * In the case that @p aut does not contain any states, this function does nothing. @@ -405,7 +405,7 @@ bool make_complete(Nfa& aut, const Alphabet& alphabet, State sink_state); bool make_complete(Nfa& aut, const utils::OrdVector& symbols, State sink_state); /** - * For each state 0,...,aut.size()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur + * For each state 0,...,aut.num_of_states()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur * on transitions from given state) to new sink state (if no new transitions are added, this sink state is not created). * In the case that @p aut does not contain any states, this function does nothing. * @@ -413,7 +413,7 @@ bool make_complete(Nfa& aut, const utils::OrdVector& symbols, State sink * @param[in] alphabet Alphabet to use for computing "missing" symbols. * @return True if some new transition (and sink state) was added to the automaton. */ -inline bool make_complete(Nfa& aut, const Alphabet& alphabet) { return make_complete(aut, alphabet, aut.size()); } +inline bool make_complete(Nfa& aut, const Alphabet& alphabet) { return make_complete(aut, alphabet, aut.num_of_states()); } /** * @brief Compute automaton accepting complement of @p aut. diff --git a/src/nfa/complement.cc b/src/nfa/complement.cc index 54e09a7d2..bbf357128 100644 --- a/src/nfa/complement.cc +++ b/src/nfa/complement.cc @@ -34,7 +34,7 @@ Nfa mata::nfa::algorithms::complement_classical(const Nfa& aut, const OrdVector< // which can be the sink state (so we do not create unnecessary one) sink_state = *result.initial.begin(); } else { - sink_state = result.size(); + sink_state = result.num_of_states(); } } else { std::unordered_map subset_map; @@ -44,12 +44,12 @@ Nfa mata::nfa::algorithms::complement_classical(const Nfa& aut, const OrdVector< if (sink_state_iter != subset_map.end()) { sink_state = sink_state_iter->second; } else { - sink_state = result.size(); + sink_state = result.num_of_states(); } } make_complete(result, symbols, sink_state); - result.final.complement(result.size()); + result.final.complement(result.num_of_states()); return result; } diff --git a/src/nfa/concatenation.cc b/src/nfa/concatenation.cc index 146deae57..a413b2813 100644 --- a/src/nfa/concatenation.cc +++ b/src/nfa/concatenation.cc @@ -27,7 +27,7 @@ Nfa concatenate(const Nfa& lhs, const Nfa& rhs, bool use_epsilon, } Nfa& Nfa::concatenate(const Nfa& aut) { - size_t n = this->size(); + size_t n = this->num_of_states(); auto upd_fnc = [&](State st) { return st + n; }; @@ -36,7 +36,7 @@ Nfa& Nfa::concatenate(const Nfa& aut) { // set accepting states utils::SparseSet new_fin{}; - new_fin.reserve(n+aut.size()); + new_fin.reserve(n+aut.num_of_states()); for(const State& aut_fin : aut.final) { new_fin.insert(upd_fnc(aut_fin)); } @@ -68,13 +68,13 @@ Nfa algorithms::concatenate_eps(const Nfa& lhs, const Nfa& rhs, const Symbol& ep // Compute concatenation of given automata. // Concatenation will proceed in the order of the passed automata: Result is 'lhs . rhs'. - if (lhs.size() == 0 || rhs.size() == 0 || lhs.initial.empty() || lhs.final.empty() || + if (lhs.num_of_states() == 0 || rhs.num_of_states() == 0 || lhs.initial.empty() || lhs.final.empty() || rhs.initial.empty() || rhs.final.empty()) { return Nfa{}; } - const unsigned long lhs_states_num{lhs.size() }; - const unsigned long rhs_states_num{rhs.size() }; + const unsigned long lhs_states_num{lhs.num_of_states() }; + const unsigned long rhs_states_num{rhs.num_of_states() }; Nfa result{}; // Concatenated automaton. StateRenaming _lhs_states_renaming{}; // Map mapping rhs states to result states. StateRenaming _rhs_states_renaming{}; // Map mapping rhs states to result states. diff --git a/src/nfa/inclusion.cc b/src/nfa/inclusion.cc index a484ce0ea..3abd0be52 100644 --- a/src/nfa/inclusion.cc +++ b/src/nfa/inclusion.cc @@ -76,7 +76,7 @@ bool mata::nfa::algorithms::is_included_antichains( // initialize WorklistType worklist = { }; - ProcessedType processed(smaller.size()); // allocate to the number of states of the smaller nfa + ProcessedType processed(smaller.num_of_states()); // allocate to the number of states of the smaller nfa // 'paths[s] == t' denotes that state 's' was accessed from state 't', // 'paths[s] == s' means that 's' is an initial state diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index a85d98554..982ae77cc 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -54,7 +54,7 @@ namespace { StateBoolArray reachable_states(const Nfa& nfa, const std::optional& states_to_consider = std::nullopt) { std::vector worklist{}; - StateBoolArray reachable(nfa.size(), false); + StateBoolArray reachable(nfa.num_of_states(), false); for (const State state: nfa.initial) { if (!states_to_consider.has_value() || states_to_consider.value()[state]) { worklist.push_back(state); @@ -89,7 +89,7 @@ StateSet Nfa::get_reachable_states() const { StateBoolArray reachable_bool_array{ reachable_states(*this) }; StateSet reachable_states{}; - const size_t num_of_states{size() }; + const size_t num_of_states{ this->num_of_states() }; for (State original_state{ 0 }; original_state < num_of_states; ++original_state) { if (reachable_bool_array[original_state]) @@ -245,8 +245,8 @@ namespace { * @return BoolVector */ BoolVector Nfa::get_useful_states() const { - BoolVector useful(this->size(),false); - std::vector node_info(this->size()); + BoolVector useful(this->num_of_states(),false); + std::vector node_info(this->num_of_states()); std::deque program_stack; std::deque tarjan_stack; unsigned long index_cnt = 0; @@ -400,7 +400,7 @@ void Nfa::print_to_mata(std::ostream &output) const { } Nfa Nfa::get_one_letter_aut(Symbol abstract_symbol) const { - Nfa digraph{size(), StateSet(initial), StateSet(final) }; + Nfa digraph{num_of_states(), StateSet(initial), StateSet(final) }; // Add directed transitions for digraph. for (const Transition& transition: delta.transitions()) { // Directly try to add the transition. Finding out whether the transition is already in the digraph @@ -487,7 +487,7 @@ Nfa& Nfa::operator=(Nfa&& other) noexcept { } State Nfa::add_state() { - const size_t num_of_states{ size() }; + const size_t num_of_states{ this->num_of_states() }; delta.increase_size(num_of_states + 1); return num_of_states; } @@ -499,7 +499,7 @@ State Nfa::add_state(State state) { return state; } -size_t Nfa::size() const { +size_t Nfa::num_of_states() const { return std::max({ static_cast(initial.domain_size()), static_cast(final.domain_size()), diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index d3639c673..d677ca865 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -67,7 +67,7 @@ namespace { std::vector quot_proj; sim_relation_symmetric.get_quotient_projection(quot_proj); - const size_t num_of_states = aut.size(); + const size_t num_of_states = aut.num_of_states(); // map each state q of aut to the state of the reduced automaton representing the simulation class of q for (State q = 0; q < num_of_states; ++q) { @@ -141,7 +141,7 @@ bool mata::nfa::make_complete(Nfa& aut, const Alphabet& alphabet, State sink_sta bool mata::nfa::make_complete(Nfa& aut, const mata::utils::OrdVector& symbols, State sink_state) { bool was_something_added{ false }; - size_t num_of_states{ aut.size() }; + size_t num_of_states{ aut.num_of_states() }; for (State state = 0; state < num_of_states; ++state) { OrdVector used_symbols{}; for (auto const &move : aut.delta[state]) { @@ -170,7 +170,7 @@ Nfa mata::nfa::remove_epsilon(const Nfa& aut, Symbol epsilon) { // TODO: grossly inefficient // first we compute the epsilon closure - const size_t num_of_states{aut.size() }; + const size_t num_of_states{aut.num_of_states() }; for (size_t i{ 0 }; i < num_of_states; ++i) { for (const auto& trans: aut.delta[i]) @@ -226,7 +226,7 @@ Nfa mata::nfa::remove_epsilon(const Nfa& aut, Symbol epsilon) { } Nfa mata::nfa::fragile_revert(const Nfa& aut) { - const size_t num_of_states{ aut.size() }; + const size_t num_of_states{ aut.num_of_states() }; Nfa result(num_of_states); @@ -351,7 +351,7 @@ Nfa mata::nfa::simple_revert(const Nfa& aut) { Nfa result; result.clear(); - const size_t num_of_states{ aut.size() }; + const size_t num_of_states{ aut.num_of_states() }; result.delta.increase_size(num_of_states); for (State sourceState{ 0 }; sourceState < num_of_states; ++sourceState) { @@ -370,7 +370,7 @@ Nfa mata::nfa::simple_revert(const Nfa& aut) { //not so great, can be removed Nfa mata::nfa::somewhat_simple_revert(const Nfa& aut) { - const size_t num_of_states{ aut.size() }; + const size_t num_of_states{ aut.num_of_states() }; Nfa result(num_of_states); @@ -416,7 +416,7 @@ bool mata::nfa::is_deterministic(const Nfa& aut) if (aut.delta.empty()) { return true; } - const size_t aut_size = aut.size(); + const size_t aut_size = aut.num_of_states(); for (size_t i = 0; i < aut_size; ++i) { for (const auto& symStates : aut.delta[i]) @@ -636,7 +636,7 @@ Nfa mata::nfa::uni(const Nfa &lhs, const Nfa &rhs) { Nfa union_nfa{ rhs }; StateRenaming lhs_state_renaming; - const size_t size = lhs.size(); + const size_t size = lhs.num_of_states(); for (State lhs_state = 0; lhs_state < size; ++lhs_state) { lhs_state_renaming[lhs_state] = union_nfa.add_state(); } diff --git a/src/re2parser.cc b/src/re2parser.cc index f50919a79..e661dc827 100644 --- a/src/re2parser.cc +++ b/src/re2parser.cc @@ -488,8 +488,8 @@ namespace { if (renumbered_states[stateTo] == mata::nfa::Limits::max_state) { renumbered_states[stateTo] = renumbered_explicit_nfa.add_state(); } - assert(renumbered_states[state] <= renumbered_explicit_nfa.size()); - assert(renumbered_states[stateTo] <= renumbered_explicit_nfa.size()); + assert(renumbered_states[state] <= renumbered_explicit_nfa.num_of_states()); + assert(renumbered_states[stateTo] <= renumbered_explicit_nfa.num_of_states()); renumbered_explicit_nfa.delta.add(renumbered_states[state], transition.symbol, renumbered_states[stateTo]); } diff --git a/src/strings/nfa-noodlification.cc b/src/strings/nfa-noodlification.cc index 91a29f141..9fe408d4d 100644 --- a/src/strings/nfa-noodlification.cc +++ b/src/strings/nfa-noodlification.cc @@ -54,14 +54,14 @@ std::vector seg_nfa::noodlify(const SegNfa& aut, const Symbol e if (segments.size() == 1) { std::shared_ptr segment = std::make_shared(segments[0]); segment->trim(); - if (segment->size() > 0 || include_empty) { + if (segment->num_of_states() > 0 || include_empty) { return {{ segment }}; } else { return {}; } } - State unused_state = aut.size(); // get some State not used in aut + State unused_state = aut.num_of_states(); // get some State not used in aut std::map, std::shared_ptr> segments_one_initial_final; segs_one_initial_final(segments, include_empty, unused_state, segments_one_initial_final); @@ -139,7 +139,7 @@ void seg_nfa::segs_one_initial_final( segment_one_final.final = {final_state }; segment_one_final = reduce(segment_one_final.trim()); - if (segment_one_final.size() > 0 || include_empty) { + if (segment_one_final.num_of_states() > 0 || include_empty) { out[std::make_pair(unused_state, final_state)] = std::make_shared(segment_one_final); } } @@ -149,7 +149,7 @@ void seg_nfa::segs_one_initial_final( segment_one_init.initial = {init_state }; segment_one_init = reduce(segment_one_init.trim()); - if (segment_one_init.size() > 0 || include_empty) { + if (segment_one_init.num_of_states() > 0 || include_empty) { out[std::make_pair(init_state, unused_state)] = std::make_shared(segment_one_init); } } @@ -160,7 +160,7 @@ void seg_nfa::segs_one_initial_final( segment_one_init_final.initial = {init_state }; segment_one_init_final.final = {final_state }; segment_one_init_final = reduce(segment_one_init_final.trim()); - if (segment_one_init_final.size() > 0 || include_empty) { + if (segment_one_init_final.num_of_states() > 0 || include_empty) { out[std::make_pair(init_state, final_state)] = std::make_shared(segment_one_init_final); } } @@ -182,14 +182,14 @@ std::vector seg_nfa::noodlify_mult_eps(const if (segments.size() == 1) { std::shared_ptr segment = std::make_shared(segments[0]); segment->trim(); - if (segment->size() > 0 || include_empty) { + if (segment->num_of_states() > 0 || include_empty) { return {{ {segment, def_eps_vector} } }; } else { return {}; } } - State unused_state = aut.size(); // get some State not used in aut + State unused_state = aut.num_of_states(); // get some State not used in aut std::map, std::shared_ptr> segments_one_initial_final; segs_one_initial_final(segments, include_empty, unused_state, segments_one_initial_final); diff --git a/src/strings/nfa-segmentation.cc b/src/strings/nfa-segmentation.cc index c2b2db2e9..112e2533a 100644 --- a/src/strings/nfa-segmentation.cc +++ b/src/strings/nfa-segmentation.cc @@ -86,7 +86,7 @@ std::deque seg_nfa::Segmentation::initia std::unordered_map seg_nfa::Segmentation::initialize_visited_map() const { std::unordered_map visited{}; - const size_t state_num = automaton.size(); + const size_t state_num = automaton.num_of_states(); for (State state{ 0 }; state < state_num; ++state) { visited[state] = false; diff --git a/src/strings/nfa-strings.cc b/src/strings/nfa-strings.cc index 7f5001a70..f7d9c3c91 100644 --- a/src/strings/nfa-strings.cc +++ b/src/strings/nfa-strings.cc @@ -152,12 +152,12 @@ std::set> mata::strings::get_word_lengths(const Nfa& aut) { /// transitions are renamed to a single symbol (e.g., `a`). aut.get_one_letter_aut(one_letter); one_letter = determinize(one_letter).trim(); - if(one_letter.size() == 0) { + if(one_letter.num_of_states() == 0) { return {}; } std::set> ret; - std::vector handles(one_letter.size(), 0); // initialized to 0 + std::vector handles(one_letter.num_of_states(), 0); // initialized to 0 assert(one_letter.initial.size() == 1); std::optional curr_state = *one_letter.initial.begin(); std::set visited; diff --git a/tests/nfa/nfa-concatenation.cc b/tests/nfa/nfa-concatenation.cc index a7a3d4bbf..7fd186a64 100644 --- a/tests/nfa/nfa-concatenation.cc +++ b/tests/nfa/nfa-concatenation.cc @@ -81,7 +81,7 @@ TEST_CASE("mata::nfa::concatenate()") { SECTION("Empty automaton without states") { result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -92,7 +92,7 @@ TEST_CASE("mata::nfa::concatenate()") { rhs.add_state(); result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -103,7 +103,7 @@ TEST_CASE("mata::nfa::concatenate()") { lhs.add_state(); result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -115,7 +115,7 @@ TEST_CASE("mata::nfa::concatenate()") { lhs.initial.insert(0); result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -127,7 +127,7 @@ TEST_CASE("mata::nfa::concatenate()") { rhs.initial.insert(0); result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -140,7 +140,7 @@ TEST_CASE("mata::nfa::concatenate()") { lhs.final.insert(0); result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -153,7 +153,7 @@ TEST_CASE("mata::nfa::concatenate()") { rhs.final.insert(0); result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -165,7 +165,7 @@ TEST_CASE("mata::nfa::concatenate()") { rhs.add_state(); result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -180,7 +180,7 @@ TEST_CASE("mata::nfa::concatenate()") { result = concatenate(lhs, rhs); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -372,7 +372,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { rhs.add_state(); result = concatenate(lhs, rhs, true); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -387,7 +387,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { result = concatenate(lhs, rhs, true); - CHECK(result.size() == 0); + CHECK(result.num_of_states() == 0); CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); @@ -418,7 +418,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial[0]); CHECK(result.final[1]); - CHECK(result.size() == 2); + CHECK(result.num_of_states() == 2); CHECK(result.delta.num_of_transitions() == 1); CHECK(result.delta.contains(0, EPSILON, 1)); } @@ -436,7 +436,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial[0]); CHECK(result.final[2]); - CHECK(result.size() == 3); + CHECK(result.num_of_states() == 3); CHECK(result.delta.num_of_transitions() == 1); CHECK(result.delta.contains(0, EPSILON, 1)); } @@ -455,7 +455,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial[0]); CHECK(result.final[2]); - CHECK(result.size() == 3); + CHECK(result.num_of_states() == 3); CHECK(result.delta.num_of_transitions() == 2); CHECK(result.delta.contains(1, 'a', 2)); CHECK(result.delta.contains(0, EPSILON, 1)); @@ -476,7 +476,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial[0]); CHECK(result.final[3]); - CHECK(result.size() == 4); + CHECK(result.num_of_states() == 4); CHECK(result.delta.num_of_transitions() == 3); CHECK(result.delta.contains(0, 'b', 1)); CHECK(result.delta.contains(2, 'a', 3)); @@ -503,7 +503,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial[0]); CHECK(result.final[3]); - CHECK(result.size() == 6); + CHECK(result.num_of_states() == 6); CHECK(result.delta.num_of_transitions() == 4); CHECK(result.delta.contains(0, 'b', 1)); CHECK(result.delta.contains(2, 'a', 3)); @@ -534,7 +534,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial[0]); CHECK(result.final[2]); - CHECK(result.size() == 3); + CHECK(result.num_of_states() == 3); CHECK(result.delta.num_of_transitions() == 3); CHECK(result.delta.contains(0, 'b', 1)); CHECK(result.delta.contains(2, 'a', 2)); @@ -557,7 +557,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial[1]); CHECK(result.initial[3]); - CHECK(result.size() == 26); + CHECK(result.num_of_states() == 26); auto shortest_words{ get_shortest_words(result) }; CHECK(shortest_words.size() == 4); @@ -576,7 +576,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { result = concatenate(rhs, lhs, true); - CHECK(result.size() == 26); + CHECK(result.num_of_states() == 26); CHECK(result.initial.size() == 1); CHECK(result.initial[4]); diff --git a/tests/nfa/nfa-intersection.cc b/tests/nfa/nfa-intersection.cc index 0e096e2b8..124823b22 100644 --- a/tests/nfa/nfa-intersection.cc +++ b/tests/nfa/nfa-intersection.cc @@ -231,7 +231,7 @@ TEST_CASE("mata::nfa::intersection() with preserving epsilon transitions") CHECK(result.is_state(prod_map[{4, 7}])); CHECK(result.is_state(prod_map[{5, 9}])); CHECK(result.is_state(prod_map[{5, 8}])); - CHECK(result.size() == 13); + CHECK(result.num_of_states() == 13); CHECK(result.initial[prod_map[{0, 0}]]); CHECK(result.initial.size() == 1); diff --git a/tests/nfa/nfa-plumbing.cc b/tests/nfa/nfa-plumbing.cc index 8585ae742..a07ee16e4 100644 --- a/tests/nfa/nfa-plumbing.cc +++ b/tests/nfa/nfa-plumbing.cc @@ -111,7 +111,7 @@ TEST_CASE("Mata::nfa::Plumbing") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::reduce(&result, lhs); CHECK(!is_lang_empty(result)); - CHECK(result.size() <= lhs.size()); + CHECK(result.num_of_states() <= lhs.num_of_states()); } SECTION("Mata::nfa::Plumbing::determinize") { @@ -133,7 +133,7 @@ TEST_CASE("Mata::nfa::Plumbing") { } SECTION("Mata::nfa::Plumbing::make_complete") { FILL_WITH_AUT_A(lhs); - mata::nfa::plumbing::make_complete(&lhs, alph, lhs.size() + 1); + mata::nfa::plumbing::make_complete(&lhs, alph, lhs.num_of_states() + 1); CHECK(!is_lang_empty(lhs)); } } diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 20d8a4fe5..2ccc9e42f 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -29,25 +29,25 @@ using OnTheFlyAlphabet = mata::OnTheFlyAlphabet; TEST_CASE("mata::nfa::size()") { Nfa nfa{}; - CHECK(nfa.size() == 0); + CHECK(nfa.num_of_states() == 0); nfa.add_state(3); - CHECK(nfa.size() == 4); + CHECK(nfa.num_of_states() == 4); nfa.clear(); nfa.add_state(); - CHECK(nfa.size() == 1); + CHECK(nfa.num_of_states() == 1); nfa.clear(); FILL_WITH_AUT_A(nfa); - CHECK(nfa.size() == 11); + CHECK(nfa.num_of_states() == 11); nfa.clear(); FILL_WITH_AUT_B(nfa); - CHECK(nfa.size() == 15); + CHECK(nfa.num_of_states() == 15); nfa = Nfa{ 0, {}, {} }; - CHECK(nfa.size() == 0); + CHECK(nfa.num_of_states() == 0); } TEST_CASE("mata::nfa::Trans::operator<<") { @@ -1050,8 +1050,8 @@ TEST_CASE("mata::nfa::complement()") {"minimize", "true"}}); CHECK(are_equivalent(cmpl, cmpl_min, &alph)); - CHECK(cmpl_min.size() == 4); - CHECK(cmpl.size() == 5); + CHECK(cmpl_min.num_of_states() == 4); + CHECK(cmpl.num_of_states() == 5); } } // }}} @@ -2044,7 +2044,7 @@ TEST_CASE("mata::nfa::reduce_size_by_simulation()") REQUIRE(result.delta.empty()); REQUIRE(result.initial[state_renaming[1]]); REQUIRE(result.final[state_renaming[2]]); - REQUIRE(result.size() == 2); + REQUIRE(result.num_of_states() == 2); REQUIRE(state_renaming[1] == state_renaming[0]); REQUIRE(state_renaming[2] != state_renaming[0]); } @@ -2073,7 +2073,7 @@ TEST_CASE("mata::nfa::reduce_size_by_simulation()") Nfa result = reduce(aut, &state_renaming); - REQUIRE(result.size() == 6); + REQUIRE(result.num_of_states() == 6); REQUIRE(result.initial[state_renaming[1]]); REQUIRE(result.initial[state_renaming[2]]); REQUIRE(result.delta.contains(state_renaming[9], 'c', state_renaming[0])); @@ -2088,7 +2088,7 @@ TEST_CASE("mata::nfa::reduce_size_by_simulation()") REQUIRE(result.final[state_renaming[3]]); result = reduce(aut.trim(), &state_renaming); - CHECK(result.size() == 3); + CHECK(result.num_of_states() == 3); CHECK(result.initial == SparseSet{ 0, 1 }); CHECK(result.final == SparseSet{ 2 }); CHECK(result.delta.num_of_transitions() == 6); @@ -2260,7 +2260,7 @@ TEST_CASE("mata::nfa::get_one_letter_aut()") Nfa digraph{aut.get_one_letter_aut() }; - REQUIRE(digraph.size() == aut.size()); + REQUIRE(digraph.num_of_states() == aut.num_of_states()); REQUIRE(digraph.delta.num_of_transitions() == 12); REQUIRE(digraph.delta.contains(1, abstract_symbol, 10)); REQUIRE(digraph.delta.contains(10, abstract_symbol, 7)); @@ -2379,7 +2379,7 @@ TEST_CASE("mata::nfa::trim()") aut.trim(); CHECK(aut.initial.size() == orig_aut.initial.size()); CHECK(aut.final.size() == orig_aut.final.size()); - CHECK(aut.size() == 4); + CHECK(aut.num_of_states() == 4); for (const Word& word: get_shortest_words(orig_aut)) { CHECK(is_in_lang(aut, Run{word,{}})); @@ -2388,7 +2388,7 @@ TEST_CASE("mata::nfa::trim()") aut.final.erase(2); // '2' is the new final state in the earlier trimmed automaton. aut.trim(); CHECK(aut.delta.empty()); - CHECK(aut.size() == 0); + CHECK(aut.num_of_states() == 0); } SECTION("With state map") { @@ -2397,7 +2397,7 @@ TEST_CASE("mata::nfa::trim()") aut.trim(&state_map); CHECK(aut.initial.size() == orig_aut.initial.size()); CHECK(aut.final.size() == orig_aut.final.size()); - CHECK(aut.size() == 4); + CHECK(aut.num_of_states() == 4); for (const Word& word: get_shortest_words(orig_aut)) { CHECK(is_in_lang(aut, Run{word,{}})); @@ -2411,7 +2411,7 @@ TEST_CASE("mata::nfa::trim()") aut.final.erase(2); // '2' is the new final state in the earlier trimmed automaton. aut.trim(&state_map); CHECK(aut.delta.empty()); - CHECK(aut.size() == 0); + CHECK(aut.num_of_states() == 0); CHECK(state_map.empty()); } } @@ -2472,24 +2472,24 @@ TEST_CASE("mata::nfa::delta.operator[]") FILL_WITH_AUT_A(aut); REQUIRE(aut.delta.num_of_transitions() == 15); aut.delta[25]; - REQUIRE(aut.size() == 20); + REQUIRE(aut.num_of_states() == 20); aut.delta.mutable_state_post(25); - REQUIRE(aut.size() == 26); + REQUIRE(aut.num_of_states() == 26); REQUIRE(aut.delta[25].empty()); aut.delta.mutable_state_post(50); - REQUIRE(aut.size() == 51); + REQUIRE(aut.num_of_states() == 51); REQUIRE(aut.delta[50].empty()); Nfa aut1 = aut; aut1.delta.mutable_state_post(60); - REQUIRE(aut1.size() == 61); + REQUIRE(aut1.num_of_states() == 61); REQUIRE(aut1.delta[60].empty()); const Nfa aut2 = aut; aut2.delta[60]; - REQUIRE(aut2.size() == 51); + REQUIRE(aut2.num_of_states() == 51); REQUIRE(aut2.delta[60].empty()); } @@ -2498,7 +2498,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { SECTION("No initial") { nfa.unify_initial(); - CHECK(nfa.size() == 10); + CHECK(nfa.num_of_states() == 10); CHECK(nfa.initial.empty()); } @@ -2507,7 +2507,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { nfa.final.insert(0); nfa.final.insert(1); nfa.unify_final(); - REQUIRE(nfa.size() == 11); + REQUIRE(nfa.num_of_states() == 11); CHECK(nfa.final.size() == 1); CHECK(nfa.final[10]); CHECK(nfa.initial[10]); @@ -2518,7 +2518,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { nfa.initial.insert(1); nfa.final.insert(0); nfa.unify_initial(); - REQUIRE(nfa.size() == 11); + REQUIRE(nfa.num_of_states() == 11); CHECK(nfa.initial.size() == 1); CHECK(nfa.initial[10]); CHECK(nfa.final[10]); @@ -2527,7 +2527,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { SECTION("Single initial") { nfa.initial.insert(0); nfa.unify_initial(); - CHECK(nfa.size() == 10); + CHECK(nfa.num_of_states() == 10); CHECK(nfa.initial.size() == 1); CHECK(nfa.initial[0]); } @@ -2536,7 +2536,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { nfa.initial.insert(0); nfa.initial.insert(1); nfa.unify_initial(); - CHECK(nfa.size() == 11); + CHECK(nfa.num_of_states() == 11); CHECK(nfa.initial.size() == 1); CHECK(nfa.initial[10]); } @@ -2548,7 +2548,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { nfa.delta.add(1, 'b', 0); nfa.delta.add(1, 'c', 1); nfa.unify_initial(); - CHECK(nfa.size() == 11); + CHECK(nfa.num_of_states() == 11); CHECK(nfa.initial.size() == 1); CHECK(nfa.initial[10]); CHECK(nfa.delta.contains(10, 'a', 3)); @@ -2561,14 +2561,14 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { SECTION("No final") { nfa.unify_final(); - CHECK(nfa.size() == 10); + CHECK(nfa.num_of_states() == 10); CHECK(nfa.final.empty()); } SECTION("Single final") { nfa.final.insert(0); nfa.unify_final(); - CHECK(nfa.size() == 10); + CHECK(nfa.num_of_states() == 10); CHECK(nfa.final.size() == 1); CHECK(nfa.final[0]); } @@ -2577,7 +2577,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { nfa.final.insert(0); nfa.final.insert(1); nfa.unify_final(); - CHECK(nfa.size() == 11); + CHECK(nfa.num_of_states() == 11); CHECK(nfa.final.size() == 1); CHECK(nfa.final[10]); } @@ -2589,7 +2589,7 @@ TEST_CASE("mata::nfa::Nfa::unify_(initial/final)()") { nfa.delta.add(4, 'b', 1); nfa.delta.add(1, 'c', 1); nfa.unify_final(); - CHECK(nfa.size() == 11); + CHECK(nfa.num_of_states() == 11); CHECK(nfa.final.size() == 1); CHECK(nfa.final[10]); CHECK(nfa.delta.contains(3, 'a', 10)); From 7428f219732c6058f20eb1fecac7825265d7e32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 08:00:55 +0200 Subject: [PATCH 08/23] Rename 'SymbolPost::size()' to 'SymbolPost::num_of_targets()' --- include/mata/nfa/delta.hh | 2 +- src/nfa/delta.cc | 6 +++--- src/nfa/operations.cc | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mata/nfa/delta.hh b/include/mata/nfa/delta.hh index 7285b618e..022303da3 100644 --- a/include/mata/nfa/delta.hh +++ b/include/mata/nfa/delta.hh @@ -72,7 +72,7 @@ public: size_t count(State s) const { return targets.count(s); } bool empty() const { return targets.empty(); } - size_t size() const { return targets.size(); } + size_t num_of_targets() const { return targets.size(); } void insert(State s); void insert(const StateSet& states); diff --git a/src/nfa/delta.cc b/src/nfa/delta.cc index f74f0fd73..af4d7f55c 100644 --- a/src/nfa/delta.cc +++ b/src/nfa/delta.cc @@ -174,7 +174,7 @@ size_t Delta::num_of_transitions() const { size_t number_of_transitions{ 0 }; for (const StatePost& state_post: state_posts_) { for (const SymbolPost& symbol_post: state_post) { - number_of_transitions += symbol_post.size(); + number_of_transitions += symbol_post.num_of_targets(); } } return number_of_transitions; @@ -287,7 +287,7 @@ std::vector Delta::renumber_targets(const std::function copied_state_post.reserve(state_post.size()); for(const SymbolPost& symbol_post: state_post) { StateSet copied_targets; - copied_targets.reserve(symbol_post.size()); + copied_targets.reserve(symbol_post.num_of_targets()); for(const State& state: symbol_post.targets) { copied_targets.push_back(std::move(target_renumberer(state))); } @@ -426,7 +426,7 @@ bool StatePost::Moves::const_iterator::operator==(const StatePost::Moves::const_ size_t StatePost::num_of_moves() const { size_t counter{ 0 }; for (const SymbolPost& symbol_post: *this) { - counter += symbol_post.size(); + counter += symbol_post.num_of_targets(); } return counter; } diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index d677ca865..585eac410 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -421,7 +421,7 @@ bool mata::nfa::is_deterministic(const Nfa& aut) { for (const auto& symStates : aut.delta[i]) { - if (symStates.size() != 1) { return false; } + if (symStates.num_of_targets() != 1) { return false; } } } From e9a9379e658166e0dff4a3bcee6d27b9a986262c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 08:04:10 +0200 Subject: [PATCH 09/23] Remove non-existent method binding --- bindings/python/libmata/nfa/nfa.pxd | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index c16587b95..0cf0b7cc2 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -46,7 +46,6 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": void push_back(CSymbolPost&) void remove(CSymbolPost&) bool empty() - size_t size() vector[CSymbolPost] ToVector() COrdVector[CSymbolPost].const_iterator cbegin() COrdVector[CSymbolPost].const_iterator cend() From cf516c4df1c4bc93bfada0ac9f669ae9f8087fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 08:40:53 +0200 Subject: [PATCH 10/23] Rename 'increase_size()' to 'allocate()' --- include/mata/nfa/delta.hh | 13 ++++++++++--- src/nfa/nfa.cc | 4 ++-- src/nfa/operations.cc | 2 +- tests/nfa/delta.cc | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/include/mata/nfa/delta.hh b/include/mata/nfa/delta.hh index 022303da3..22447708b 100644 --- a/include/mata/nfa/delta.hh +++ b/include/mata/nfa/delta.hh @@ -347,9 +347,16 @@ public: void clear() { state_posts_.clear(); } - void increase_size(size_t n) { - assert(n >= state_posts_.size()); - state_posts_.resize(n); + /** + * @brief Allocate state posts up to @p num_of_states states, creating empty @c StatePost for yet unallocated state + * posts. + * + * @param[in] num_of_states Number of states in @c Delta to allocate state posts for. Have to be at least + * num_of_states() + 1. + */ + void allocate(const size_t num_of_states) { + assert(num_of_states >= this->num_of_states()); + state_posts_.resize(num_of_states); } /** diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index 982ae77cc..68c8a6f27 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -488,13 +488,13 @@ Nfa& Nfa::operator=(Nfa&& other) noexcept { State Nfa::add_state() { const size_t num_of_states{ this->num_of_states() }; - delta.increase_size(num_of_states + 1); + delta.allocate(num_of_states + 1); return num_of_states; } State Nfa::add_state(State state) { if (state >= delta.num_of_states()) { - delta.increase_size(state + 1); + delta.allocate(state + 1); } return state; } diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 585eac410..9c17638a3 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -352,7 +352,7 @@ Nfa mata::nfa::simple_revert(const Nfa& aut) { result.clear(); const size_t num_of_states{ aut.num_of_states() }; - result.delta.increase_size(num_of_states); + result.delta.allocate(num_of_states); for (State sourceState{ 0 }; sourceState < num_of_states; ++sourceState) { for (const SymbolPost &transition: aut.delta[sourceState]) { diff --git a/tests/nfa/delta.cc b/tests/nfa/delta.cc index 27a87393c..2e4c551c2 100644 --- a/tests/nfa/delta.cc +++ b/tests/nfa/delta.cc @@ -344,7 +344,7 @@ TEST_CASE("mata::nfa::Delta iteration over transitions") { SECTION("Sparse automaton") { const size_t state_num = 'r'+1; - nfa.delta.increase_size(state_num); + nfa.delta.reserve(state_num); nfa.delta.add('q', 'a', 'r'); nfa.delta.add('q', 'b', 'r'); From d39d7383752ee6e4162f2025bb2b08ad76bd42af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 09:15:20 +0200 Subject: [PATCH 11/23] Explain variadic number of arguments template --- include/mata/nfa/nfa.hh | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 166c64dc1..1753ee6df 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -273,20 +273,24 @@ public: */ void fill_alphabet(const Nfa& nfa, mata::OnTheFlyAlphabet& alphabet); +// Allow variadic number of arguments of the same type. +// +// Using parameter pack and variadic arguments. // Adapted from: https://www.fluentcpp.com/2019/01/25/variadic-number-function-parameters-type/. +/// Pack of bools for reasoning about a sequence of parameters. template struct bool_pack{}; -/// Checks for all types in the pack. +/// Check that for all values in a pack @p Ts are 'true'. template using conjunction = std::is_same, bool_pack>; -/// Checks whether all types are 'Nfa'. -template using AreAllNfas = typename conjunction...>::type; +/// Check that all types in a sequence of parameters @p Ts are of type @p T. +template using AreAllOfType = typename conjunction...>::type; /** - * Create alphabet from variable number of NFAs. + * Create alphabet from variadic number of NFAs given as arguments. * @tparam[in] Nfas Type Nfa. * @param[in] nfas NFAs to create alphabet from. * @return Created alphabet. */ -template> +template> inline OnTheFlyAlphabet create_alphabet(const Nfas&... nfas) { mata::OnTheFlyAlphabet alphabet{}; auto f = [&alphabet](const Nfa& aut) { From 836c0f43467a89ad068825232d9882d92f90cc6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 09:59:50 +0200 Subject: [PATCH 12/23] Move `is_lang_empty()` to `Nfa` as a method --- bindings/python/libmata/nfa/nfa.pxd | 3 +- bindings/python/libmata/nfa/nfa.pyx | 22 ++- bindings/python/tests/test_nfa.py | 6 +- examples/example03-lang-empty.cc | 4 +- .../notebooks/example-03-exploring-maze.ipynb | 4 +- include/mata/nfa/nfa.hh | 16 +- src/nfa/inclusion.cc | 2 +- src/nfa/operations.cc | 66 +++----- src/nfa/universal.cc | 2 +- src/strings/nfa-noodlification.cc | 10 +- .../src/bench-bool-comb-cox-diff.cc | 2 +- .../src/bench-bool-comb-cox-inter.cc | 2 +- .../src/bench-bool-comb-intersect.cc | 2 +- tests/nfa/nfa-concatenation.cc | 32 ++-- tests/nfa/nfa-intersection.cc | 2 +- tests/nfa/nfa-plumbing.cc | 20 +-- tests/nfa/nfa.cc | 36 ++--- tests/re2parser.cc | 152 +++++++++--------- 18 files changed, 180 insertions(+), 203 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 0cf0b7cc2..587c665e4 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -167,10 +167,11 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": void remove_epsilon(Symbol) except + void clear() size_t num_of_states() + bool is_lang_empty(CRun*) + bool is_deterministic() # Automata tests cdef bool c_is_deterministic "mata::nfa::is_deterministic" (CNfa&) - cdef bool c_is_lang_empty "mata::nfa::is_lang_empty" (CNfa&, CRun*) cdef bool c_is_universal "mata::nfa::is_universal" (CNfa&, CAlphabet&, ParameterMap&) except + cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CRun*, CAlphabet*, ParameterMap&) except + diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index cbf39cf32..85aa5eb12 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -526,6 +526,16 @@ cdef class Nfa: self.thisptr.get().trim(&state_map) return self, {k: v for k, v in state_map} + def is_lang_empty(self, Run run = None): + """Check if language of automaton is empty. + + :return: true if the language of NFA is empty; path of states as a counter example if not. + """ + if run: + return self.thisptr.get().is_lang_empty(run.thisptr) + else: + return self.thisptr.get().is_lang_empty(NULL) + def get_one_letter_aut(self) -> Nfa: """Unify transitions to create a directed graph with at most a single transition between two states (using only one letter for all transitions). @@ -947,18 +957,6 @@ def is_deterministic(Nfa lhs): """ return mata_nfa.c_is_deterministic(dereference(lhs.thisptr.get())) -def is_lang_empty(Nfa lhs, Run run = None): - """Checks if language of automaton lhs is empty, if not, returns path of states as counter - example. - - :param Nfa lhs: - :return: true if the lhs is empty, counter example if lhs is not empty - """ - if run: - return mata_nfa.c_is_lang_empty(dereference(lhs.thisptr.get()), run.thisptr) - else: - return mata_nfa.c_is_lang_empty(dereference(lhs.thisptr.get()), NULL) - def is_universal(Nfa lhs, alph.Alphabet alphabet, params = None): """Tests if lhs is universal wrt given alphabet diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index 814baf498..780351346 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -227,7 +227,7 @@ def test_encode_word(): def test_language_emptiness(fa_one_divisible_by_two): cex = mata_nfa.Run() - assert not mata_nfa.is_lang_empty(fa_one_divisible_by_two, cex) + assert not fa_one_divisible_by_two.is_lang_empty(cex) assert cex.path == [0, 1, 2] assert cex.word == [1, 1] @@ -237,7 +237,7 @@ def test_language_emptiness(fa_one_divisible_by_two): lhs.add_transition(1, 0, 2) lhs.add_transition(2, 0, 3) cex = mata_nfa.Run() - assert mata_nfa.is_lang_empty(lhs, cex) + assert lhs.is_lang_empty(cex) assert cex.word == [] assert cex.path == [] @@ -340,7 +340,7 @@ def test_concatenate(): result = mata_nfa.concatenate(lhs, rhs) - assert not mata_nfa.is_lang_empty(result) + assert not result.is_lang_empty() shortest_words = mata_strings.get_shortest_words(result) assert len(shortest_words) == 1 assert [ord('b'), ord('a')] in shortest_words diff --git a/examples/example03-lang-empty.cc b/examples/example03-lang-empty.cc index 67447ce27..0b9861b73 100644 --- a/examples/example03-lang-empty.cc +++ b/examples/example03-lang-empty.cc @@ -9,7 +9,7 @@ using namespace mata::nfa; int main() { Nfa aut(10); - std::cout << "Language empty: " << is_lang_empty(aut) << "\n"; + std::cout << "Language empty: " << aut.is_lang_empty() << "\n"; aut.initial = {0, 2}; aut.final = {4}; @@ -29,5 +29,5 @@ int main() { aut.delta.add(4, 0, 4); aut.delta.add(4, 2, 8); - std::cout << "Language empty: " << is_lang_empty(aut) << "\n"; + std::cout << "Language empty: " << aut.is_lang_empty() << "\n"; } diff --git a/examples/notebooks/example-03-exploring-maze.ipynb b/examples/notebooks/example-03-exploring-maze.ipynb index b9456f92f..038ed7efe 100644 --- a/examples/notebooks/example-03-exploring-maze.ipynb +++ b/examples/notebooks/example-03-exploring-maze.ipynb @@ -930,7 +930,7 @@ ], "source": [ "solution = mata_nfa.Run()\n", - "is_empty = mata_nfa.is_lang_empty(automaton_maze, solution)\n", + "is_empty = automaton_maze.is_lang_empty(solution)\n", "is_empty" ] }, @@ -1007,7 +1007,7 @@ "bwidth, bheight = 60, 10\n", "big_maze = generate_maze(bwidth, bheight)\n", "big_automaton_maze = to_automaton(big_maze)\n", - "is_empty = mata_nfa.is_lang_empty(big_automaton_maze, solution)\n", + "is_empty = big_automaton_maze.is_lang_empty(solution)\n", "if not is_empty:\n", " plot_maze(big_maze, path_to_goal=solution.path)\n", "else:\n", diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 1753ee6df..74c4d6b80 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -264,6 +264,14 @@ public: // TODO: Relict from VATA. What to do with inclusion/ universality/ this post function? Revise all of them. StateSet post(const StateSet& states, const Symbol& symbol) const; + + /** + * Check whether the language of NFA is empty. + * @param[out] cex Counter-example path for a case the language is not empty. + * @return True if the language is empty, false otherwise. + */ + bool is_lang_empty(Run* cex = nullptr) const; + }; // struct Nfa. /** @@ -328,14 +336,6 @@ OnTheFlyAlphabet create_alphabet(const std::vector& nfas); */ OnTheFlyAlphabet create_alphabet(const std::vector& nfas); -/** - * Check whether is the language of the automaton empty. - * @param[in] aut Automaton to check. - * @param[out] cex Counter-example path for a case the language is not empty. - * @return True if the language is empty, false otherwise. - */ -bool is_lang_empty(const Nfa& aut, Run* cex = nullptr); - Nfa uni(const Nfa &lhs, const Nfa &rhs); /** diff --git a/src/nfa/inclusion.cc b/src/nfa/inclusion.cc index 3abd0be52..38f00774f 100644 --- a/src/nfa/inclusion.cc +++ b/src/nfa/inclusion.cc @@ -37,7 +37,7 @@ bool mata::nfa::algorithms::is_included_naive( } Nfa nfa_isect = intersection(smaller, bigger_cmpl, false, nullptr); - return is_lang_empty(nfa_isect, cex); + return nfa_isect.is_lang_empty(cex); } // is_included_naive }}} diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 9c17638a3..659577b16 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -537,71 +537,51 @@ bool mata::nfa::is_prfx_in_lang(const Nfa& aut, const Run& run) return aut.final.intersects_with(cur); } -bool mata::nfa::is_lang_empty(const Nfa& aut, Run* cex) -{ // {{{ - std::list worklist( - aut.initial.begin(), aut.initial.end()); - std::unordered_set processed( - aut.initial.begin(), aut.initial.end()); +bool mata::nfa::Nfa::is_lang_empty(Run* cex) const { + std::list worklist(initial.begin(), initial.end()); + std::unordered_set processed(initial.begin(), initial.end()); // 'paths[s] == t' denotes that state 's' was accessed from state 't', // 'paths[s] == s' means that 's' is an initial state std::map paths; - for (State s : worklist) - { // initialize - paths[s] = s; - } + // Initialize paths. + for (const State s: worklist) { paths[s] = s; } - while (!worklist.empty()) - { - State state = worklist.front(); + State state; + while (!worklist.empty()) { + state = worklist.front(); worklist.pop_front(); - if (aut.final[state]) - { - // TODO process the CEX - if (nullptr != cex) - { + if (final[state]) { + if (nullptr != cex) { cex->path.clear(); cex->path.push_back(state); - while (paths[state] != state) - { + while (paths[state] != state) { state = paths[state]; cex->path.push_back(state); } - std::reverse(cex->path.begin(), cex->path.end()); - cex->word = get_word_for_path(aut, *cex).first.word; + cex->word = get_word_for_path(*this, *cex).first.word; } return false; } - if (aut.delta.empty()) - continue; + if (delta.empty()) { continue; } - for (const auto& symb_stateset : aut.delta[state]) - { - for (const auto& tgt_state : symb_stateset.targets) - { + for (const SymbolPost& symbol_post: delta[state]) { + for (const State& target: symbol_post.targets) { bool inserted; - tie(std::ignore, inserted) = processed.insert(tgt_state); - if (inserted) - { - worklist.push_back(tgt_state); - // also set that tgt_state was accessed from state - paths[tgt_state] = state; - } - else - { - // the invariant - assert(haskey(paths, tgt_state)); - } + tie(std::ignore, inserted) = processed.insert(target); + if (inserted) { + worklist.push_back(target); + // Also set that tgt_state was accessed from state. + paths[target] = state; + } else { assert(haskey(paths, target)); /* Invariant. */ } } } - } - + } // while (!worklist.empty()). return true; -} // is_lang_empty }}} +} // is_lang_empty(). Nfa mata::nfa::algorithms::minimize_brzozowski(const Nfa& aut) { diff --git a/src/nfa/universal.cc b/src/nfa/universal.cc index 396b3289f..567e5bc0a 100644 --- a/src/nfa/universal.cc +++ b/src/nfa/universal.cc @@ -35,7 +35,7 @@ bool mata::nfa::algorithms::is_universal_naive( { // {{{ Nfa cmpl = complement(aut, alphabet); - return is_lang_empty(cmpl, cex); + return cmpl.is_lang_empty(cex); } // is_universal_naive }}} diff --git a/src/strings/nfa-noodlification.cc b/src/strings/nfa-noodlification.cc index 9fe408d4d..09820ac9b 100644 --- a/src/strings/nfa-noodlification.cc +++ b/src/strings/nfa-noodlification.cc @@ -269,7 +269,7 @@ std::vector seg_nfa::noodlify_for_equation( (*lhs_aut_iter).get().unify_final(); } - if (lhs_automata.empty() || is_lang_empty(rhs_automaton)) { return {}; } + if (lhs_automata.empty() || rhs_automaton.is_lang_empty()) { return {}; } // Automaton representing the left side concatenated over epsilon transitions. Nfa concatenated_lhs{ *lhs_aut_begin }; @@ -280,7 +280,7 @@ std::vector seg_nfa::noodlify_for_equation( auto product_pres_eps_trans{ intersection(concatenated_lhs, rhs_automaton, true).trim() }; - if (is_lang_empty(product_pres_eps_trans)) { + if (product_pres_eps_trans.is_lang_empty()) { return {}; } if (utils::haskey(params, "reduce")) { @@ -318,7 +318,7 @@ std::vector seg_nfa::noodlify_for_equation( } } - if (lhs_automata.empty() || is_lang_empty(rhs_automaton)) { return {}; } + if (lhs_automata.empty() || rhs_automaton.is_lang_empty()) { return {}; } // Automaton representing the left side concatenated over epsilon transitions. Nfa concatenated_lhs{ *(*lhs_aut_begin) }; @@ -329,7 +329,7 @@ std::vector seg_nfa::noodlify_for_equation( auto product_pres_eps_trans{ intersection(concatenated_lhs, rhs_automaton, true).trim() }; - if (is_lang_empty(product_pres_eps_trans)) { + if (product_pres_eps_trans.is_lang_empty()) { return {}; } if (!reduce_value.empty()) { @@ -388,7 +388,7 @@ std::vector seg_nfa::noodlify_for_equation( auto product_pres_eps_trans{ intersection_eps(concatenated_lhs, concatenated_rhs, true, epsilons).trim() }; - if (is_lang_empty(product_pres_eps_trans)) { + if (product_pres_eps_trans.is_lang_empty()) { return {}; } if (utils::haskey(params, "reduce")) { diff --git a/tests-integration/src/bench-bool-comb-cox-diff.cc b/tests-integration/src/bench-bool-comb-cox-diff.cc index 50b581e2c..7821ee34e 100644 --- a/tests-integration/src/bench-bool-comb-cox-diff.cc +++ b/tests-integration/src/bench-bool-comb-cox-diff.cc @@ -36,7 +36,7 @@ int main(int argc, char *argv[]) { TIME_BEGIN(emptiness_check); Nfa compl_rhs = complement(rhs, alphabet); Nfa intersect_aut = intersection(lhs, compl_rhs); - is_lang_empty(intersect_aut); + intersect_aut.is_lang_empty(); TIME_END(emptiness_check); return EXIT_SUCCESS; diff --git a/tests-integration/src/bench-bool-comb-cox-inter.cc b/tests-integration/src/bench-bool-comb-cox-inter.cc index 9d78ff428..2118b8de8 100644 --- a/tests-integration/src/bench-bool-comb-cox-inter.cc +++ b/tests-integration/src/bench-bool-comb-cox-inter.cc @@ -34,7 +34,7 @@ int main(int argc, char *argv[]) { TIME_BEGIN(emptiness_check); Nfa intersect_aut = intersection(lhs, rhs); - is_lang_empty(intersect_aut); + intersect_aut.is_lang_empty(); TIME_END(emptiness_check); return EXIT_SUCCESS; diff --git a/tests-integration/src/bench-bool-comb-intersect.cc b/tests-integration/src/bench-bool-comb-intersect.cc index 51c76b6d7..76a46ea52 100644 --- a/tests-integration/src/bench-bool-comb-intersect.cc +++ b/tests-integration/src/bench-bool-comb-intersect.cc @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) { for (unsigned int i = 1; i < uargc; ++i) { result = intersection(result, automata[i]); } - is_lang_empty(result); + result.is_lang_empty(); TIME_END(intersection_emptiness); return EXIT_SUCCESS; diff --git a/tests/nfa/nfa-concatenation.cc b/tests/nfa/nfa-concatenation.cc index 7fd186a64..a744643f4 100644 --- a/tests/nfa/nfa-concatenation.cc +++ b/tests/nfa/nfa-concatenation.cc @@ -85,7 +85,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("One empty automaton without states") { @@ -96,7 +96,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Other empty automaton without states") { @@ -107,7 +107,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("One empty automaton without states with other with initial states") { @@ -119,7 +119,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Other empty automaton without states with other with initial states") { @@ -131,7 +131,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("One empty automaton without states with other non-empty automaton") { @@ -144,7 +144,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Other empty automaton without states with other non-empty automaton") { @@ -157,7 +157,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Empty automaton") { @@ -169,7 +169,7 @@ TEST_CASE("mata::nfa::concatenate()") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Empty language") { @@ -194,7 +194,7 @@ TEST_CASE("mata::nfa::concatenate()") { rhs.initial.insert(0); result = concatenate(lhs, rhs); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Single state automata accepting an empty string") { @@ -207,7 +207,7 @@ TEST_CASE("mata::nfa::concatenate()") { result = concatenate(lhs, rhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); CHECK(is_in_lang(result, Run{ {}, {} })); CHECK(result.delta.empty()); } @@ -357,7 +357,7 @@ TEST_CASE("mata::nfa::concatenate()") { rhs.delta.add(5, 116, 1); result = concatenate(lhs, rhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); // TODO: Add more checks. } } @@ -376,7 +376,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Empty language") { @@ -402,7 +402,7 @@ TEST_CASE("mata::nfa::concatenate() over epsilon symbol") { rhs.initial.insert(0); result = concatenate(lhs, rhs, true); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Single state automata accepting an empty string") @@ -646,7 +646,7 @@ TEST_CASE("mata::nfa::concatenate() inplace") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("One empty automaton without states") { @@ -659,7 +659,7 @@ TEST_CASE("mata::nfa::concatenate() inplace") { CHECK(result.initial.empty()); CHECK(result.final.empty()); CHECK(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Automaton A concatenate automaton B") { @@ -708,7 +708,7 @@ TEST_CASE("mata::nfa::concatenate() inplace") { rhs.delta.add(5, 116, 1); result = lhs.concatenate(rhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); // TODO: Add more checks. } } diff --git a/tests/nfa/nfa-intersection.cc b/tests/nfa/nfa-intersection.cc index 124823b22..ffa35c1e5 100644 --- a/tests/nfa/nfa-intersection.cc +++ b/tests/nfa/nfa-intersection.cc @@ -182,7 +182,7 @@ TEST_CASE("mata::nfa::intersection()") REQUIRE(res.initial[prod_map[{1, 4}]]); REQUIRE(res.initial[prod_map[{3, 4}]]); - REQUIRE(is_lang_empty(res)); + REQUIRE(res.is_lang_empty()); } } // }}} diff --git a/tests/nfa/nfa-plumbing.cc b/tests/nfa/nfa-plumbing.cc index a07ee16e4..f373273b7 100644 --- a/tests/nfa/nfa-plumbing.cc +++ b/tests/nfa/nfa-plumbing.cc @@ -78,62 +78,62 @@ TEST_CASE("Mata::nfa::Plumbing") { FILL_WITH_AUT_A(lhs); FILL_WITH_AUT_B(lhs); mata::nfa::plumbing::concatenate(&result, lhs, rhs); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::intersection") { FILL_WITH_AUT_A(lhs); FILL_WITH_AUT_B(lhs); mata::nfa::plumbing::intersection(&result, lhs, rhs); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::union") { FILL_WITH_AUT_A(lhs); FILL_WITH_AUT_B(lhs); mata::nfa::plumbing::uni(&result, lhs, rhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::remove_epsilon") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::remove_epsilon(&result, lhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::revert") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::revert(&result, lhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::reduce") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::reduce(&result, lhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); CHECK(result.num_of_states() <= lhs.num_of_states()); } SECTION("Mata::nfa::Plumbing::determinize") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::determinize(&result, lhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::minimize") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::minimize(&result, lhs); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::complement") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::complement(&result, lhs, alph); - CHECK(!is_lang_empty(result)); + CHECK(!result.is_lang_empty()); } SECTION("Mata::nfa::Plumbing::make_complete") { FILL_WITH_AUT_A(lhs); mata::nfa::plumbing::make_complete(&lhs, alph, lhs.num_of_states() + 1); - CHECK(!is_lang_empty(lhs)); + CHECK(!lhs.empty_language()); } } diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 2ccc9e42f..8391a137b 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -175,7 +175,7 @@ TEST_CASE("mata::nfa::is_lang_empty()") SECTION("An empty automaton has an empty language") { - REQUIRE(is_lang_empty(aut)); + REQUIRE(aut.is_lang_empty()); } SECTION("An automaton with a state that is both initial and final does not have an empty language") @@ -183,7 +183,7 @@ TEST_CASE("mata::nfa::is_lang_empty()") aut.initial = {1, 2}; aut.final = {2, 3}; - bool is_empty = is_lang_empty(aut, &cex); + bool is_empty = aut.is_lang_empty(&cex); REQUIRE(!is_empty); } @@ -204,19 +204,19 @@ TEST_CASE("mata::nfa::is_lang_empty()") SECTION("with final states") { aut.final = {7}; - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); } SECTION("without final states") { - REQUIRE(is_lang_empty(aut)); + REQUIRE(aut.is_lang_empty()); } SECTION("another complicated automaton") { FILL_WITH_AUT_A(aut); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); } SECTION("a complicated automaton with unreachable final states") @@ -224,7 +224,7 @@ TEST_CASE("mata::nfa::is_lang_empty()") FILL_WITH_AUT_A(aut); aut.final = {13}; - REQUIRE(is_lang_empty(aut)); + REQUIRE(aut.is_lang_empty()); } } @@ -233,7 +233,7 @@ TEST_CASE("mata::nfa::is_lang_empty()") aut.initial = {1, 2}; aut.final = {2, 3}; - bool is_empty = is_lang_empty(aut, &cex); + bool is_empty = aut.is_lang_empty(&cex); REQUIRE(!is_empty); // check the counterexample @@ -252,7 +252,7 @@ TEST_CASE("mata::nfa::is_lang_empty()") aut.delta.add(3, 'e', 5); aut.delta.add(4, 'c', 8); - bool is_empty = is_lang_empty(aut, &cex); + bool is_empty = aut.is_lang_empty(&cex); REQUIRE(!is_empty); // check the counterexample @@ -357,7 +357,7 @@ TEST_CASE("mata::nfa::is_lang_empty_cex()") aut.delta.add(3, 'e', 5); aut.delta.add(4, 'c', 8); - bool is_empty = is_lang_empty(aut, &cex); + bool is_empty = aut.is_lang_empty(&cex); REQUIRE(!is_empty); // check the counterexample @@ -380,7 +380,7 @@ TEST_CASE("mata::nfa::determinize()") REQUIRE(result.final.empty()); REQUIRE(result.delta.empty()); - CHECK(is_lang_empty(result)); + CHECK(result.is_lang_empty()); } SECTION("simple automaton 1") @@ -479,7 +479,7 @@ TEST_CASE("mata::nfa::construct() correct calls") aut = builder::construct(parsec); - REQUIRE(is_lang_empty(aut)); + REQUIRE(aut.is_lang_empty()); } SECTION("construct a simple non-empty automaton accepting the empty word") @@ -490,7 +490,7 @@ TEST_CASE("mata::nfa::construct() correct calls") aut = builder::construct(parsec); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); } SECTION("construct an automaton with more than one initial/final states") @@ -515,7 +515,7 @@ TEST_CASE("mata::nfa::construct() correct calls") aut = builder::construct(parsec, &alphabet); Run cex; - REQUIRE(!is_lang_empty(aut, &cex)); + REQUIRE(!aut.is_lang_empty(&cex)); auto word_bool_pair = get_word_for_path(aut, cex); REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word == encode_word(&alphabet, { "a"}).word); @@ -599,9 +599,9 @@ TEST_CASE("mata::nfa::construct() from IntermediateAut correct calls") SECTION("construct an empty automaton") { inter_aut.automaton_type = mata::IntermediateAut::AutomatonType::NFA; - REQUIRE(is_lang_empty(aut)); + REQUIRE(aut.is_lang_empty()); aut = builder::construct(inter_aut); - REQUIRE(is_lang_empty(aut)); + REQUIRE(aut.is_lang_empty()); } SECTION("construct a simple non-empty automaton accepting the empty word from intermediate automaton") @@ -617,7 +617,7 @@ TEST_CASE("mata::nfa::construct() from IntermediateAut correct calls") aut = builder::construct(inter_aut); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); } SECTION("construct an automaton with more than one initial/final states from intermediate automaton") @@ -686,7 +686,7 @@ TEST_CASE("mata::nfa::construct() from IntermediateAut correct calls") plumbing::construct(&aut, inter_aut, &alphabet); Run cex; - REQUIRE(!is_lang_empty(aut, &cex)); + REQUIRE(!aut.is_lang_empty(&cex)); auto word_bool_pair = get_word_for_path(aut, cex); REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word == encode_word(&alphabet, { "a" }).word); @@ -956,7 +956,7 @@ TEST_CASE("mata::nfa::complement()") cmpl = complement(aut, alph, {{"algorithm", "classical"}, {"minimize", "false"}}); - CHECK(is_lang_empty(cmpl)); + CHECK(cmpl.is_lang_empty()); } SECTION("empty automaton accepting epsilon") diff --git a/tests/re2parser.cc b/tests/re2parser.cc index 853532791..a3d28afc3 100644 --- a/tests/re2parser.cc +++ b/tests/re2parser.cc @@ -15,16 +15,14 @@ bool is_in_lang(const Nfa& aut, const Word& word) // Some example regexes were taken from RegExr under GPL v3: https://github.com/gskinner/regexr. -TEST_CASE("mata::Parser basic_parsing") -{ // {{{ +TEST_CASE("mata::Parser basic_parsing") { Nfa aut; - SECTION("Empty expression") - { + SECTION("Empty expression") { mata::parser::create_nfa(&aut, ""); REQUIRE(aut.final.size() == aut.initial.size()); REQUIRE(aut.delta.empty()); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); REQUIRE(is_in_lang(aut, Word{})); } @@ -32,7 +30,7 @@ TEST_CASE("mata::Parser basic_parsing") { mata::parser::create_nfa(&aut, "abcd"); REQUIRE(!aut.delta.empty()); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); REQUIRE(!is_in_lang(aut, Word{'a','b','c'})); REQUIRE(is_in_lang(aut, Word{'a','b','c','d'})); REQUIRE(!is_in_lang(aut, Word{'a','b','c','d','d'})); @@ -43,7 +41,7 @@ TEST_CASE("mata::Parser basic_parsing") { mata::parser::create_nfa(&aut, "\\x7f"); REQUIRE(!aut.delta.empty()); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); REQUIRE(is_in_lang(aut, Word{127})); } @@ -51,7 +49,7 @@ TEST_CASE("mata::Parser basic_parsing") { mata::parser::create_nfa(&aut, ".*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); REQUIRE(is_in_lang(aut, Word{'w','h','a','t','e','v','e','r'})); REQUIRE(is_in_lang(aut, Word{127})); REQUIRE(is_in_lang(aut, Word{0x7f})); @@ -63,7 +61,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Special character") { mata::parser::create_nfa(&aut, "\\t"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{'\t'})); CHECK(!is_in_lang(aut, Word{'t'})); CHECK(!is_in_lang(aut, Word{})); @@ -72,7 +70,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Whitespace") { mata::parser::create_nfa(&aut, "a\\sb"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{'a', '\t', 'b'})); CHECK(!is_in_lang(aut, Word{})); } @@ -81,7 +79,7 @@ TEST_CASE("mata::Parser basic_parsing") { mata::parser::create_nfa(&aut, "ab*cd*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); REQUIRE(is_in_lang(aut, Word{'a','b','c'})); REQUIRE(is_in_lang(aut, Word{'a','b','c','d'})); REQUIRE(is_in_lang(aut, Word{'a','c','d'})); @@ -142,7 +140,7 @@ TEST_CASE("mata::Parser basic_parsing") } CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{'b'})); CHECK(is_in_lang(aut, Word{'a','b'})); CHECK(is_in_lang(aut, Word{'a','a','b'})); @@ -153,7 +151,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Complex regex") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -171,7 +169,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Complex regex with additional plus") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -188,7 +186,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Reduced complex regex with additional plus") { mata::parser::create_nfa(&aut, "(e)(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -205,7 +203,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Reduced complex regex with additional plus 2") { mata::parser::create_nfa(&aut, "(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -223,7 +221,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Reduced complex regex with additional plus 2.5") { mata::parser::create_nfa(&aut, "(w*)(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -241,7 +239,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Reduced complex regex with additional plus 2.63") { mata::parser::create_nfa(&aut, "w*b+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -259,7 +257,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Reduced complex regex with additional plus 2.75") { mata::parser::create_nfa(&aut, "w(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -277,7 +275,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Reduced complex regex with additional plus 2.85") { mata::parser::create_nfa(&aut, "w*(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -295,7 +293,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Reduced complex regex with additional plus 3") { mata::parser::create_nfa(&aut, "(b+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -308,7 +306,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Complex regex 2") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)(b*)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -327,7 +325,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("Complex regex 2 with additional plus") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)+(b*)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -346,7 +344,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("a+b+") { mata::parser::create_nfa(&aut, "a+b+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -360,7 +358,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("a+b+a*") { mata::parser::create_nfa(&aut, "a+b+a*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -376,7 +374,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("a+(b+)a*") { mata::parser::create_nfa(&aut, "a+(b+)a*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -392,7 +390,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(a+(b+)a*)") { mata::parser::create_nfa(&aut, "(a+(b+)a*)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'a', 'a'})); @@ -408,7 +406,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(a+b*a*)") { mata::parser::create_nfa(&aut, "(a+b*a*)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -424,7 +422,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("a+a+") { mata::parser::create_nfa(&aut, "a+a+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -435,7 +433,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(a+)a+") { mata::parser::create_nfa(&aut, "(a+)a+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -446,7 +444,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("a(a+)") { mata::parser::create_nfa(&aut, "a(a+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'a'})); @@ -457,7 +455,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(a+)b") { mata::parser::create_nfa(&aut, "(a+)b"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'a', 'b'})); @@ -468,7 +466,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b(a+)") { mata::parser::create_nfa(&aut, "b(a+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b', 'a'})); @@ -479,7 +477,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b|(a+)") { mata::parser::create_nfa(&aut, "b|(a+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -492,7 +490,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b|a+") { mata::parser::create_nfa(&aut, "b|a+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -505,7 +503,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b|a") { mata::parser::create_nfa(&aut, "b|a"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -518,7 +516,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b|a*") { mata::parser::create_nfa(&aut, "b|a*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -531,7 +529,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("bba+") { mata::parser::create_nfa(&aut, "bba+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'b'})); @@ -545,7 +543,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b*ba+") { mata::parser::create_nfa(&aut, "b*ba+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'b'})); @@ -561,7 +559,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b*ca+") { mata::parser::create_nfa(&aut, "b*ca+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'b'})); @@ -578,7 +576,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[abcd]") { mata::parser::create_nfa(&aut, "[abcd]"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -590,7 +588,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[abcd]*") { mata::parser::create_nfa(&aut, "[abcd]*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -607,7 +605,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[abcd]*e*") { mata::parser::create_nfa(&aut, "[abcd]*e*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -630,7 +628,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[abcd]*e+") { mata::parser::create_nfa(&aut, "[abcd]*e+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'b'})); @@ -654,7 +652,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[abcd]*.*") { mata::parser::create_nfa(&aut, "[abcd]*.*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -685,7 +683,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[abcd]*.+") { mata::parser::create_nfa(&aut, "[abcd]*.+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -716,7 +714,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[a-c]+") { mata::parser::create_nfa(&aut, "[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -733,7 +731,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("d[a-c]+") { mata::parser::create_nfa(&aut, "d[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'b'})); @@ -750,7 +748,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("d*[a-c]+") { mata::parser::create_nfa(&aut, "d*[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a'})); CHECK(is_in_lang(aut, Word{'b'})); @@ -768,7 +766,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[^a-c]") { mata::parser::create_nfa(&aut, "[^a-c]"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'b'})); @@ -782,7 +780,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(ha)+") { mata::parser::create_nfa(&aut, "(ha)+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'h'})); @@ -797,7 +795,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(ha)*") { mata::parser::create_nfa(&aut, "(ha)*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'a'})); CHECK(!is_in_lang(aut, Word{'h'})); @@ -812,7 +810,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b\\w{2,3}") { mata::parser::create_nfa(&aut, "b\\w{2,3}"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'b'})); CHECK(!is_in_lang(aut, Word{'b', 'e'})); @@ -824,7 +822,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b\\w+?") { mata::parser::create_nfa(&aut, "b\\w+?"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'b'})); CHECK(is_in_lang(aut, Word{'b', 'e'})); @@ -836,7 +834,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("b(a|e|i)d") { mata::parser::create_nfa(&aut, "b(a|e|i)d"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'b', 'a', 'd'})); CHECK(!is_in_lang(aut, Word{'b', 'u', 'd'})); @@ -848,7 +846,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[ab](c|d)") { mata::parser::create_nfa(&aut, "[ab](c|d)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a', 'c'})); CHECK(is_in_lang(aut, Word{'b', 'c'})); @@ -863,7 +861,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[ab](c|d)") { mata::parser::create_nfa(&aut, "[ab](c|d)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a', 'c'})); CHECK(is_in_lang(aut, Word{'b', 'c'})); @@ -878,7 +876,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("[ab]+(c|d)") { mata::parser::create_nfa(&aut, "[ab]+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a', 'c'})); CHECK(is_in_lang(aut, Word{'b', 'c'})); @@ -896,7 +894,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("([ab])+(c|d)") { mata::parser::create_nfa(&aut, "([ab])+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a', 'c'})); CHECK(is_in_lang(aut, Word{'b', 'c'})); @@ -914,7 +912,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(([ab])+)(c|d)") { mata::parser::create_nfa(&aut, "(([ab])+)(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a', 'c'})); CHECK(is_in_lang(aut, Word{'b', 'c'})); @@ -932,7 +930,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("g|((([ab])+)(c|d))") { mata::parser::create_nfa(&aut, "(g|(([ab])+))(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'a', 'c'})); CHECK(is_in_lang(aut, Word{'b', 'c'})); @@ -952,7 +950,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("g|([ab])+(c|d)") { mata::parser::create_nfa(&aut, "g|([ab])+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'g'})); CHECK(is_in_lang(aut, Word{'a', 'c'})); @@ -979,7 +977,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(((c)*)((a)*))") { mata::parser::create_nfa(&aut, "(((c)*)((a)*))"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'c'})); CHECK(is_in_lang(aut, Word{'a'})); @@ -996,7 +994,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("((c*)((a)*))") { mata::parser::create_nfa(&aut, "((c*)((a)*))"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'c'})); CHECK(is_in_lang(aut, Word{'a'})); @@ -1013,7 +1011,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(c*(a*))") { mata::parser::create_nfa(&aut, "(c*(a*))"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'c'})); CHECK(is_in_lang(aut, Word{'a'})); @@ -1030,7 +1028,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(c*a*)") { mata::parser::create_nfa(&aut, "(c*a*)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'c'})); CHECK(is_in_lang(aut, Word{'a'})); @@ -1047,7 +1045,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("c*a*") { mata::parser::create_nfa(&aut, "c*a*"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(is_in_lang(aut, Word{})); CHECK(is_in_lang(aut, Word{'c'})); CHECK(is_in_lang(aut, Word{'a'})); @@ -1064,7 +1062,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(((c)+)((a)+))") { mata::parser::create_nfa(&aut, "(((c)+)((a)+))"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'c'})); CHECK(!is_in_lang(aut, Word{'a'})); @@ -1088,7 +1086,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("((c+)((a)+))") { mata::parser::create_nfa(&aut, "((c+)((a)+))"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'c'})); CHECK(!is_in_lang(aut, Word{'a'})); @@ -1112,7 +1110,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("((c+)(a+))") { mata::parser::create_nfa(&aut, "((c+)(a+))"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'c'})); CHECK(!is_in_lang(aut, Word{'a'})); @@ -1136,7 +1134,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(c+)(a+)") { mata::parser::create_nfa(&aut, "(c+)(a+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'c'})); CHECK(!is_in_lang(aut, Word{'a'})); @@ -1160,7 +1158,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("c+(a+)") { mata::parser::create_nfa(&aut, "c+(a+)"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'c'})); CHECK(!is_in_lang(aut, Word{'a'})); @@ -1184,7 +1182,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("(c+)a+") { mata::parser::create_nfa(&aut, "(c+)a+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'c'})); CHECK(!is_in_lang(aut, Word{'a'})); @@ -1208,7 +1206,7 @@ TEST_CASE("mata::Parser basic_parsing") SECTION("c+a+") { mata::parser::create_nfa(&aut, "c+a+"); CHECK(!aut.delta.empty()); - CHECK(!is_lang_empty(aut)); + CHECK(!aut.is_lang_empty()); CHECK(!is_in_lang(aut, Word{})); CHECK(!is_in_lang(aut, Word{'c'})); CHECK(!is_in_lang(aut, Word{'a'})); @@ -1238,7 +1236,7 @@ TEST_CASE("mata::Parser error") mata::nfa::Nfa aut; mata::parser::create_nfa(&aut, "((aa)*)*(b)*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!is_lang_empty(aut)); + REQUIRE(!aut.is_lang_empty()); REQUIRE(is_in_lang(aut, Word{'a','a','b'})); REQUIRE(!is_in_lang(aut, Word{'a','b'})); } @@ -1250,9 +1248,9 @@ TEST_CASE("mata::Parser error") mata::parser::create_nfa(&aut1, "[qQrR]*"); mata::parser::create_nfa(&aut2, "[qr]*"); REQUIRE(!aut1.delta.empty()); - REQUIRE(!is_lang_empty(aut1)); + REQUIRE(!aut1.is_lang_empty()); REQUIRE(!aut2.delta.empty()); - REQUIRE(!is_lang_empty(aut2)); + REQUIRE(!aut2.is_lang_empty()); REQUIRE(is_in_lang(aut1, Word{'Q','R','q','r'})); REQUIRE(is_in_lang(aut2, Word{'q','r','q','r'})); REQUIRE(!is_in_lang(aut2, Word{'q','R','q'})); From 8315d81a3b9e190aa34ebdc24c9028b1837243cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 10:00:29 +0200 Subject: [PATCH 13/23] Move 'get_transitions_to()' to 'Delta' --- bindings/python/libmata/nfa/nfa.pxd | 2 +- bindings/python/libmata/nfa/nfa.pyx | 2 +- include/mata/nfa/delta.hh | 9 +++++++++ include/mata/nfa/nfa.hh | 8 -------- src/nfa/delta.cc | 14 ++++++++++++++ src/nfa/nfa.cc | 16 +--------------- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 587c665e4..a7cee302d 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -83,6 +83,7 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": COrdVector[CSymbolPost].const_iterator epsilon_symbol_posts(CStatePost& post, Symbol epsilon) size_t num_of_transitions() CTransitions transitions() + vector[CTrans] get_transitions_to(State) COrdVector[Symbol] get_used_symbols() cdef cppclass CRun "mata::nfa::Run": @@ -157,7 +158,6 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": State add_state() State add_state(State) void print_to_DOT(ostream) - vector[CTrans] get_transitions_to(State) CNfa& trim(StateRenaming*) void get_one_letter_aut(CNfa&) bool is_epsilon(Symbol) diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index 85aa5eb12..9b4bdd836 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -436,7 +436,7 @@ cdef class Nfa: :return: List mata_nfa.CTrans: List of transitions leading to state_to. """ - cdef vector[CTrans] c_transitions = self.thisptr.get().get_transitions_to(state_to) + cdef vector[CTrans] c_transitions = self.thisptr.get().delta.get_transitions_to(state_to) trans = [] for c_transition in c_transitions: trans.append(Transition(c_transition.source, c_transition.symbol, c_transition.target)) diff --git a/include/mata/nfa/delta.hh b/include/mata/nfa/delta.hh index 22447708b..37f7b119a 100644 --- a/include/mata/nfa/delta.hh +++ b/include/mata/nfa/delta.hh @@ -434,6 +434,15 @@ public: */ Transitions transitions() const; + /** + * Get transitions leading to @p state_to. + * @param state_to[in] Target state for transitions to get. + * @return Transitions leading to @p state_to. + * + * Operation is slow, traverses over all symbol posts. + */ + std::vector get_transitions_to(State state_to) const; + /** * Iterate over @p epsilon symbol posts under the given @p state. * @param[in] state State from which epsilon transitions are checked. diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 74c4d6b80..2c2ac6426 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -199,14 +199,6 @@ public: */ Nfa& concatenate(const Nfa& aut); - /** - * Get transitions leading to @p state_to. - * @param state_to[in] Target state for transitions to get. - * @return Sequence of @c Trans transitions leading to @p state_to. - * (!slow!, traverses the entire delta) - */ - std::vector get_transitions_to(State state_to) const; - /** * Unify transitions to create a directed graph with at most a single transition between two states. * @param[in] abstract_symbol Abstract symbol to use for transitions in digraph. diff --git a/src/nfa/delta.cc b/src/nfa/delta.cc index af4d7f55c..a0e8ec66e 100644 --- a/src/nfa/delta.cc +++ b/src/nfa/delta.cc @@ -59,6 +59,20 @@ StatePost::const_iterator Delta::epsilon_symbol_posts(const StatePost& state_pos return state_post.end(); } +std::vector Delta::get_transitions_to(const State state_to) const { + std::vector transitions_to_state{}; + const size_t num_of_states{ this->num_of_states() }; + for (State state_from{ 0 }; state_from < num_of_states; ++state_from) { + for (const SymbolPost& state_from_move: state_post(state_from)) { + const auto target_state{ state_from_move.targets.find(state_to) }; + if (target_state != state_from_move.targets.end()) { + transitions_to_state.emplace_back(state_from, state_from_move.symbol, state_to); + } + } + } + return transitions_to_state; +} + void Delta::add(State source, Symbol symbol, State target) { const State max_state{ std::max(source, target) }; if (max_state >= state_posts_.size()) { diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index 68c8a6f27..57c422c6b 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -414,20 +414,6 @@ void Nfa::get_one_letter_aut(Nfa& result) const { result = get_one_letter_aut(); } -std::vector Nfa::get_transitions_to(State state_to) const { - std::vector transitions_to_state{}; - const size_t num_of_states{ delta.num_of_states() }; - for (State state_from{ 0 }; state_from < num_of_states; ++state_from) { - for (const SymbolPost& state_from_move: delta[state_from]) { - const auto target_state{ state_from_move.targets.find(state_to) }; - if (target_state != state_from_move.targets.end()) { - transitions_to_state.emplace_back(state_from, state_from_move.symbol, state_to ); - } - } - } - return transitions_to_state; -} - StateSet Nfa::post(const StateSet& states, const Symbol& symbol) const { StateSet res{}; if (delta.empty()) { @@ -464,7 +450,7 @@ void Nfa::unify_final() { if (final.empty() || final.size() == 1) { return; } const State new_final_state{ add_state() }; for (const auto& orig_final_state: final) { - const auto transitions_to{ get_transitions_to(orig_final_state) }; + const auto transitions_to{ delta.get_transitions_to(orig_final_state) }; for (const auto& transitions: transitions_to) { delta.add(transitions.source, transitions.symbol, new_final_state); } From 72635ef7ec3c399a939247eabeeb16c75cba8b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 11:00:45 +0200 Subject: [PATCH 14/23] Move 'is_deterministic()' to 'Nfa' as a method --- bindings/python/libmata/nfa/nfa.pxd | 1 - bindings/python/libmata/nfa/nfa.pyx | 14 +++++------ bindings/python/tests/test_nfa.py | 10 ++++---- include/mata/nfa/nfa.hh | 13 +++++++---- src/nfa/operations.cc | 15 +++++------- tests/nfa/nfa.cc | 36 +++++++++++++---------------- 6 files changed, 40 insertions(+), 49 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index a7cee302d..5086b0bb4 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -171,7 +171,6 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": bool is_deterministic() # Automata tests - cdef bool c_is_deterministic "mata::nfa::is_deterministic" (CNfa&) cdef bool c_is_universal "mata::nfa::is_universal" (CNfa&, CAlphabet&, ParameterMap&) except + cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CRun*, CAlphabet*, ParameterMap&) except + diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index 9b4bdd836..dff707689 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -536,6 +536,12 @@ cdef class Nfa: else: return self.thisptr.get().is_lang_empty(NULL) + def is_deterministic(self): + """Tests if the NFA is determinstic. + + :return: true if the NFA is deterministic. + """ + return self.thisptr.get().is_deterministic() def get_one_letter_aut(self) -> Nfa: """Unify transitions to create a directed graph with at most a single transition between two states (using only one letter for all transitions). @@ -949,14 +955,6 @@ def compute_relation(Nfa lhs, params = None): return result # Tests -def is_deterministic(Nfa lhs): - """Tests if the lhs is determinstic - - :param Nfa lhs: non-determinstic finite automaton - :return: true if the lhs is deterministic - """ - return mata_nfa.c_is_deterministic(dereference(lhs.thisptr.get())) - def is_universal(Nfa lhs, alph.Alphabet alphabet, params = None): """Tests if lhs is universal wrt given alphabet diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index 780351346..7d6b63de4 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -185,16 +185,14 @@ def test_post(binary_alphabet): def test_determinisation(nfa_two_states_uni, dfa_one_state_uni): - """ - Tests determinisation - """ + """Tests determinisation.""" lhs = nfa_two_states_uni - assert not mata_nfa.is_deterministic(lhs) + assert not lhs.is_deterministic() rhs = dfa_one_state_uni - assert mata_nfa.is_deterministic(rhs) + assert rhs.is_deterministic() chs, sm_map = mata_nfa.determinize_with_subset_map(lhs) - assert mata_nfa.is_deterministic(chs) + assert chs.is_deterministic() assert sm_map == {(0,): 0, (0, 1): 1} diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 2c2ac6426..4005400a4 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -264,6 +264,14 @@ public: */ bool is_lang_empty(Run* cex = nullptr) const; + /** + * @brief Test whether an automaton is deterministic. + * + * I.e., whether it has exactly one initial state and every state has at most one outgoing transition over every + * symbol. + * Checks the whole automaton, not only the reachable part + */ + bool is_deterministic() const; }; // struct Nfa. /** @@ -565,11 +573,6 @@ Nfa somewhat_simple_revert(const Nfa& aut); // Removing epsilon transitions Nfa remove_epsilon(const Nfa& aut, Symbol epsilon = EPSILON); -/// Test whether an automaton is deterministic, i.e., whether it has exactly -/// one initial state and every state has at most one outgoing transition over -/// every symbol. Checks the whole automaton, not only the reachable part -bool is_deterministic(const Nfa& aut); - /// Test for automaton completeness wrt an alphabet. An automaton is complete /// if every reachable state has at least one outgoing transition over every /// symbol. diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 659577b16..fdced0b09 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -410,17 +410,14 @@ Nfa mata::nfa::revert(const Nfa& aut) { //return somewhat_simple_revert(aut); } -bool mata::nfa::is_deterministic(const Nfa& aut) -{ - if (aut.initial.size() != 1) { return false; } +bool mata::nfa::Nfa::is_deterministic() const { + if (initial.size() != 1) { return false; } - if (aut.delta.empty()) { return true; } + if (delta.empty()) { return true; } - const size_t aut_size = aut.num_of_states(); - for (size_t i = 0; i < aut_size; ++i) - { - for (const auto& symStates : aut.delta[i]) - { + const size_t aut_size = num_of_states(); + for (size_t i = 0; i < aut_size; ++i) { + for (const auto& symStates : delta[i]) { if (symStates.num_of_targets() != 1) { return false; } } } diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 8391a137b..484c66cad 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -1761,61 +1761,57 @@ TEST_CASE("mata::nfa::revert()") } // }}} -TEST_CASE("mata::nfa::is_deterministic()") +TEST_CASE("mata::nfa::Nfa::is_deterministic()") { // {{{ Nfa aut('s'+1); - SECTION("(almost) empty automaton") - { + SECTION("(almost) empty automaton") { // no initial states - REQUIRE(!is_deterministic(aut)); + REQUIRE(!aut.is_deterministic()); // add an initial state aut.initial.insert('q'); - REQUIRE(is_deterministic(aut)); + REQUIRE(aut.is_deterministic()); // add the same initial state aut.initial.insert('q'); - REQUIRE(is_deterministic(aut)); + REQUIRE(aut.is_deterministic()); // add another initial state aut.initial.insert('r'); - REQUIRE(!is_deterministic(aut)); + REQUIRE(!aut.is_deterministic()); // add a final state aut.final.insert('q'); - REQUIRE(!is_deterministic(aut)); + REQUIRE(!aut.is_deterministic()); } - SECTION("trivial automata") - { + SECTION("trivial automata") { aut.initial.insert('q'); aut.delta.add('q', 'a', 'r'); - REQUIRE(is_deterministic(aut)); + REQUIRE(aut.is_deterministic()); // unreachable states aut.delta.add('s', 'a', 'r'); - REQUIRE(is_deterministic(aut)); + REQUIRE(aut.is_deterministic()); // transitions over a different symbol aut.delta.add('q', 'b', 'h'); - REQUIRE(is_deterministic(aut)); + REQUIRE(aut.is_deterministic()); // nondeterminism aut.delta.add('q', 'a', 's'); - REQUIRE(!is_deterministic(aut)); + REQUIRE(!aut.is_deterministic()); } - SECTION("larger automaton 1") - { + SECTION("larger automaton 1") { FILL_WITH_AUT_A(aut); - REQUIRE(!is_deterministic(aut)); + REQUIRE(!aut.is_deterministic()); } - SECTION("larger automaton 2") - { + SECTION("larger automaton 2") { FILL_WITH_AUT_B(aut); - REQUIRE(!is_deterministic(aut)); + REQUIRE(!aut.is_deterministic()); } } // }}} From 45f715545c52f48f53c9e33d0989755f232425c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Thu, 7 Sep 2023 11:01:37 +0200 Subject: [PATCH 15/23] Move 'is_complete()' to 'Nfa' as a method --- bindings/python/libmata/nfa/nfa.pxd | 3 ++- bindings/python/libmata/nfa/nfa.pyx | 25 +++++++++++++------------ bindings/python/tests/test_nfa.py | 14 +++++++------- include/mata/nfa/nfa.hh | 12 +++++++----- src/nfa/operations.cc | 25 ++++++++++++++----------- tests/nfa/nfa.cc | 16 ++++++++-------- 6 files changed, 51 insertions(+), 44 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 5086b0bb4..495acc177 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -169,6 +169,8 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": size_t num_of_states() bool is_lang_empty(CRun*) bool is_deterministic() + bool is_complete(CAlphabet*) except + + bool is_complete() except + # Automata tests cdef bool c_is_universal "mata::nfa::is_universal" (CNfa&, CAlphabet&, ParameterMap&) except + @@ -176,7 +178,6 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CRun*, CAlphabet*, ParameterMap&) except + cdef bool c_are_equivalent "mata::nfa::are_equivalent" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) cdef bool c_are_equivalent "mata::nfa::are_equivalent" (CNfa&, CNfa&, ParameterMap&) - cdef bool c_is_complete "mata::nfa::is_complete" (CNfa&, CAlphabet&) except + cdef bool c_is_in_lang "mata::nfa::is_in_lang" (CNfa&, CRun&) cdef bool c_is_prfx_in_lang "mata::nfa::is_prfx_in_lang" (CNfa&, CRun&) diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index dff707689..bef649d6f 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -542,6 +542,19 @@ cdef class Nfa: :return: true if the NFA is deterministic. """ return self.thisptr.get().is_deterministic() + + def is_complete(self, alph.Alphabet alphabet = None): + """Test if automaton is complete. + + :param alph.Alphabet alphabet: Alphabet to check completeness againts. If 'None', self.alphabet is used. If + self.alphabet is empty, throws an exception. + :return: true if the automaton is complete. + """ + if alphabet: + return self.thisptr.get().is_complete(alphabet.as_base()) + else: + return self.thisptr.get().is_complete() + def get_one_letter_aut(self) -> Nfa: """Unify transitions to create a directed graph with at most a single transition between two states (using only one letter for all transitions). @@ -1058,18 +1071,6 @@ def equivalence_check(Nfa lhs, Nfa rhs, alph.Alphabet alphabet = None, params = } ) -def is_complete(Nfa lhs, alph.Alphabet alphabet): - """Test if automaton is complete - - :param Nf lhs: tested automaton - :param OnTheFlyAlphabet alphabet: alphabet of the automaton - :return: true if the automaton is complete - """ - return mata_nfa.c_is_complete( - dereference(lhs.thisptr.get()), - dereference(alphabet.as_base()) - ) - def is_in_lang(Nfa lhs, vector[Symbol] word): """Tests if word is in language diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index 7d6b63de4..c4631d6f5 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -366,23 +366,23 @@ def test_completeness( alph = alphabets.OnTheFlyAlphabet() alph.translate_symbol("a") alph.translate_symbol("b") - assert mata_nfa.is_complete(fa_one_divisible_by_two, alph) - assert mata_nfa.is_complete(fa_one_divisible_by_four, alph) - assert mata_nfa.is_complete(fa_one_divisible_by_eight, alph) + assert fa_one_divisible_by_two.is_complete(alph) + assert fa_one_divisible_by_four.is_complete(alph) + assert fa_one_divisible_by_eight.is_complete(alph) l = mata_nfa.Nfa(1) l.make_initial_state(0) l.add_transition(0, 0, 0) - assert not mata_nfa.is_complete(l, alph) + assert not l.is_complete(alph) l.add_transition(0, 1, 0) - assert mata_nfa.is_complete(l, alph) + assert l.is_complete(alph) r = mata_nfa.Nfa(1) r.make_initial_state(0) r.add_transition(0, 0, 0) - assert not mata_nfa.is_complete(r, alph) + assert not r.is_complete(alph) mata_nfa.make_complete(r, 1, alph) - assert mata_nfa.is_complete(r, alph) + assert r.is_complete(alph) def test_in_language( diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 4005400a4..fb1177cf5 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -272,6 +272,13 @@ public: * Checks the whole automaton, not only the reachable part */ bool is_deterministic() const; + + /** + * @brief Test for automaton completeness with regard to an alphabet. + * + * An automaton is complete if every reachable state has at least one outgoing transition over every symbol. + */ + bool is_complete(Alphabet const* alphabet = nullptr) const; }; // struct Nfa. /** @@ -573,11 +580,6 @@ Nfa somewhat_simple_revert(const Nfa& aut); // Removing epsilon transitions Nfa remove_epsilon(const Nfa& aut, Symbol epsilon = EPSILON); -/// Test for automaton completeness wrt an alphabet. An automaton is complete -/// if every reachable state has at least one outgoing transition over every -/// symbol. -bool is_complete(const Nfa& aut, const Alphabet& alphabet); - std::pair get_word_for_path(const Nfa& aut, const Run& run); /// Checks whether a string is in the language of an automaton diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index fdced0b09..889eccb1b 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -424,26 +424,29 @@ bool mata::nfa::Nfa::is_deterministic() const { return true; } -bool mata::nfa::is_complete(const Nfa& aut, const Alphabet& alphabet) -{ - utils::OrdVector symbs_ls = alphabet.get_alphabet_symbols(); +bool mata::nfa::Nfa::is_complete(Alphabet const* alphabet) const { + if (alphabet == nullptr) { + if (this->alphabet != nullptr) { + alphabet = this->alphabet; + } else { + throw std::runtime_error("Checking for completeness without any alphabet to check againts."); + } + } + utils::OrdVector symbs_ls = alphabet->get_alphabet_symbols(); utils::OrdVector symbs(symbs_ls); // TODO: make a general function for traversal over reachable states that can // be shared by other functions? - std::list worklist(aut.initial.begin(), - aut.initial.end()); - std::unordered_set processed(aut.initial.begin(), - aut.initial.end()); + std::list worklist(initial.begin(), initial.end()); + std::unordered_set processed(initial.begin(), initial.end()); - while (!worklist.empty()) - { + while (!worklist.empty()) { State state = *worklist.begin(); worklist.pop_front(); size_t n = 0; // counter of symbols - if (!aut.delta.empty()) { - for (const auto &symb_stateset: aut.delta[state]) { + if (!delta.empty()) { + for (const auto &symb_stateset: delta[state]) { ++n; if (!haskey(symbs, symb_stateset.symbol)) { throw std::runtime_error(std::to_string(__func__) + diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 484c66cad..9121c344f 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -1824,17 +1824,17 @@ TEST_CASE("mata::nfa::is_complete()") OnTheFlyAlphabet alph{}; // is complete for the empty alphabet - REQUIRE(is_complete(aut, alph)); + REQUIRE(aut.is_complete(&alph)); alph.translate_symb("a1"); alph.translate_symb("a2"); // the empty automaton is complete even for a non-empty alphabet - REQUIRE(is_complete(aut, alph)); + REQUIRE(aut.is_complete(&alph)); // add a non-reachable state (the automaton should still be complete) aut.delta.add('q', alph["a1"], 'q'); - REQUIRE(is_complete(aut, alph)); + REQUIRE(aut.is_complete(&alph)); } SECTION("small automaton") @@ -1856,10 +1856,10 @@ TEST_CASE("mata::nfa::is_complete()") aut.delta.add(14, alph["b"], 12); aut.final.insert({2, 12}); - REQUIRE(!is_complete(aut, alph)); + REQUIRE(!aut.is_complete(&alph)); make_complete(aut, alph, 100); - REQUIRE(is_complete(aut, alph)); + REQUIRE(aut.is_complete(&alph)); } SECTION("using a non-alphabet symbol") @@ -1873,7 +1873,7 @@ TEST_CASE("mata::nfa::is_complete()") aut.delta.add(4, alph["b"], 6); aut.delta.add(6, 100, 4); - CHECK_THROWS_WITH(is_complete(aut, alph), + CHECK_THROWS_WITH(aut.is_complete(&alph), Catch::Contains("symbol that is not in the provided alphabet")); } } // }}} @@ -2662,9 +2662,9 @@ TEST_CASE("A segmentation fault in the make_complement") { r.initial = {0}; r.delta.add(0, 0, 0); - REQUIRE(not is_complete(r, alph)); + REQUIRE(not r.is_complete(&alph)); make_complete(r, alph, 1); - REQUIRE(is_complete(r, alph)); + REQUIRE(r.is_complete(&alph)); } TEST_CASE("mata::nfa:: create simple automata") { From 9d9530e95604130d16cdeb5c0c0eefec1eae34b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 11 Sep 2023 10:09:13 +0200 Subject: [PATCH 16/23] Remove unnecessary else branch after return --- src/alphabet.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/alphabet.cc b/src/alphabet.cc index f78a4b5e9..e480a3cb9 100644 --- a/src/alphabet.cc +++ b/src/alphabet.cc @@ -61,9 +61,8 @@ Symbol mata::OnTheFlyAlphabet::translate_symb(const std::string& str) { const auto it_insert_pair = symbol_map_.insert({str, next_symbol_value_}); if (it_insert_pair.second) { return next_symbol_value_++; - } else { - return it_insert_pair.first->second; } + return it_insert_pair.first->second; // TODO: How can the user specify to throw exceptions when we encounter an unknown symbol? How to specify that // the alphabet should have only the previously fixed symbols? From 44566e8929509bf0ecad7b60cb7b8be2c323d8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 11 Sep 2023 10:42:21 +0200 Subject: [PATCH 17/23] Move 'fill_alphabet()' to 'Nfa' --- include/mata/nfa/nfa.hh | 16 ++++++++-------- src/nfa/operations.cc | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index fb1177cf5..a7508b6af 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -279,14 +279,14 @@ public: * An automaton is complete if every reachable state has at least one outgoing transition over every symbol. */ bool is_complete(Alphabet const* alphabet = nullptr) const; -}; // struct Nfa. -/** - * Fill @p alphabet with symbols from @p nfa. - * @param[in] nfa NFA with symbols to fill @p alphabet with. - * @param[out] alphabet Alphabet to be filled with symbols from @p nfa. - */ -void fill_alphabet(const Nfa& nfa, mata::OnTheFlyAlphabet& alphabet); + /** + * Fill @p alphabet with symbols from @p nfa. + * @param[in] nfa NFA with symbols to fill @p alphabet with. + * @param[out] alphabet Alphabet to be filled with symbols from @p nfa. + */ + void fill_alphabet(mata::OnTheFlyAlphabet& alphabet) const; +}; // struct Nfa. // Allow variadic number of arguments of the same type. // @@ -309,7 +309,7 @@ template> inline OnTheFlyAlphabet create_alphabet(const Nfas&... nfas) { mata::OnTheFlyAlphabet alphabet{}; auto f = [&alphabet](const Nfa& aut) { - fill_alphabet(aut, alphabet); + aut.fill_alphabet(alphabet); }; (f(nfas), ...); return alphabet; diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 889eccb1b..c87b996c6 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -774,8 +774,8 @@ std::ostream& std::operator<<(std::ostream& os, const Nfa& nfa) { return os; } -void mata::nfa::fill_alphabet(const Nfa& nfa, OnTheFlyAlphabet& alphabet) { - for (const StatePost& state_post: nfa.delta) { +void mata::nfa::Nfa::fill_alphabet(OnTheFlyAlphabet& alphabet) const { + for (const StatePost& state_post: this->delta) { for (const SymbolPost& symbol_post: state_post) { alphabet.update_next_symbol_value(symbol_post.symbol); alphabet.try_add_new_symbol(std::to_string(symbol_post.symbol), symbol_post.symbol); @@ -786,7 +786,7 @@ void mata::nfa::fill_alphabet(const Nfa& nfa, OnTheFlyAlphabet& alphabet) { mata::OnTheFlyAlphabet mata::nfa::create_alphabet(const std::vector>& nfas) { mata::OnTheFlyAlphabet alphabet{}; for (const auto& nfa: nfas) { - fill_alphabet(nfa, alphabet); + nfa.get().fill_alphabet(alphabet); } return alphabet; } @@ -794,7 +794,7 @@ mata::OnTheFlyAlphabet mata::nfa::create_alphabet(const std::vector>& nfas) { mata::OnTheFlyAlphabet alphabet{}; for (const auto& nfa: nfas) { - fill_alphabet(nfa, alphabet); + nfa.get().fill_alphabet(alphabet); } return alphabet; } @@ -802,7 +802,7 @@ mata::OnTheFlyAlphabet mata::nfa::create_alphabet(const std::vector& nfas) { mata::OnTheFlyAlphabet alphabet{}; for (const Nfa* const nfa: nfas) { - fill_alphabet(*nfa, alphabet); + nfa->fill_alphabet(alphabet); } return alphabet; } @@ -810,7 +810,7 @@ mata::OnTheFlyAlphabet mata::nfa::create_alphabet(const std::vector mata::OnTheFlyAlphabet mata::nfa::create_alphabet(const std::vector& nfas) { mata::OnTheFlyAlphabet alphabet{}; for (const Nfa* const nfa: nfas) { - fill_alphabet(*nfa, alphabet); + nfa->fill_alphabet(alphabet); } return alphabet; } From 7aace471522390b21a115c9ee10f0dc2cdcfc5c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 11 Sep 2023 12:13:47 +0200 Subject: [PATCH 18/23] Move 'is_universal()' to 'Nfa' --- bindings/python/libmata/nfa/nfa.pxd | 2 +- bindings/python/libmata/nfa/nfa.pyx | 35 ++++++++----------- bindings/python/tests/test_nfa.py | 4 +-- .../notebooks/example-01-ws1s-formulae.ipynb | 2 +- include/mata/nfa/nfa.hh | 14 ++++---- src/nfa/universal.cc | 17 ++++----- tests/nfa/nfa.cc | 24 ++++++------- tests/re2parser.cc | 2 +- 8 files changed, 45 insertions(+), 55 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 495acc177..540b6e378 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -171,9 +171,9 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": bool is_deterministic() bool is_complete(CAlphabet*) except + bool is_complete() except + + bool is_universal(CAlphabet&, ParameterMap&) except + # Automata tests - cdef bool c_is_universal "mata::nfa::is_universal" (CNfa&, CAlphabet&, ParameterMap&) except + cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CRun*, CAlphabet*, ParameterMap&) except + cdef bool c_are_equivalent "mata::nfa::are_equivalent" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index bef649d6f..60314b3ff 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -709,7 +709,22 @@ cdef class Nfa: cdef CSymbolPost epsilon_transitions = dereference(c_epsilon_symbol_posts_iter) return SymbolPost(epsilon_transitions.symbol, epsilon_transitions.targets.ToVector()) + def is_universal(self, alph.Alphabet alphabet, params = None): + """Tests if NFA is universal with regard to the given alphabet. + :param OnTheFlyAlphabet alphabet: on the fly alphabet. + :param dict params: additional params to the function, currently supports key 'algorithm', + which determines used universality test. + :return: true if NFA is universal. + """ + params = params or {'algorithm': 'antichains'} + return self.thisptr.get().is_universal( + dereference(alphabet.as_base()), + { + k.encode('utf-8'): v.encode('utf-8') if isinstance(v, str) else v + for k, v in params.items() + } + ) def get_symbols(self): """Return a set of symbols used on the transitions in NFA. @@ -720,7 +735,6 @@ cdef class Nfa: return {s for s in symbols} - # Operations def determinize_with_subset_map(Nfa lhs): """Determinize the lhs automaton @@ -968,25 +982,6 @@ def compute_relation(Nfa lhs, params = None): return result # Tests -def is_universal(Nfa lhs, alph.Alphabet alphabet, params = None): - """Tests if lhs is universal wrt given alphabet - - :param Nfa lhs: automaton tested for universality - :param OnTheFlyAlphabet alphabet: on the fly alphabet - :param dict params: additional params to the function, currently supports key 'algorithm', - which determines used universality test - :return: true if lhs is universal - """ - params = params or {'algorithm': 'antichains'} - return mata_nfa.c_is_universal( - dereference(lhs.thisptr.get()), - dereference(alphabet.as_base()), - { - k.encode('utf-8'): v.encode('utf-8') if isinstance(v, str) else v - for k, v in params.items() - } - ) - def is_included_with_cex(Nfa lhs, Nfa rhs, alph.Alphabet alphabet = None, params = None): """Test inclusion between two automata diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index c4631d6f5..2e520db65 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -244,14 +244,14 @@ def test_universality(fa_one_divisible_by_two): alph = alphabets.OnTheFlyAlphabet() alph.translate_symbol("a") alph.translate_symbol("b") - assert mata_nfa.is_universal(fa_one_divisible_by_two, alph) == False + assert fa_one_divisible_by_two.is_universal(alph) == False l = mata_nfa.Nfa(1) l.make_initial_state(0) l.add_transition(0, 0, 0) l.add_transition(0, 1, 0) l.make_final_state(0) - assert mata_nfa.is_universal(l, alph) == True + assert l.is_universal(alph) == True def test_inclusion( diff --git a/examples/notebooks/example-01-ws1s-formulae.ipynb b/examples/notebooks/example-01-ws1s-formulae.ipynb index bcea7c51d..cb8de81fb 100644 --- a/examples/notebooks/example-01-ws1s-formulae.ipynb +++ b/examples/notebooks/example-01-ws1s-formulae.ipynb @@ -1015,7 +1015,7 @@ } ], "source": [ - "mata_nfa.is_universal(minimized_formula, config['alphabet'])" + "minimized_formula.is_universal(config['alphabet'])" ] } ], diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index a7508b6af..573ef07d8 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -286,6 +286,12 @@ public: * @param[out] alphabet Alphabet to be filled with symbols from @p nfa. */ void fill_alphabet(mata::OnTheFlyAlphabet& alphabet) const; + + /// Is the language of the automaton universal? + bool is_universal(const Alphabet& alphabet, Run* cex = nullptr, + const ParameterMap& params = {{ "algorithm", "antichains" }}) const; + /// Is the language of the automaton universal? + bool is_universal(const Alphabet& alphabet, const ParameterMap& params) const; }; // struct Nfa. // Allow variadic number of arguments of the same type. @@ -488,14 +494,6 @@ Nfa determinize(const Nfa& aut, std::unordered_map *subset_map Nfa reduce(const Nfa &aut, StateRenaming *state_renaming = nullptr, const ParameterMap& params = {{ "algorithm", "simulation" } }); -/// Is the language of the automaton universal? -bool is_universal(const Nfa& aut, const Alphabet& alphabet, Run* cex = nullptr, - const ParameterMap& params = {{ "algorithm", "antichains" }}); - -inline bool is_universal(const Nfa& aut, const Alphabet& alphabet, const ParameterMap& params) { - return is_universal(aut, alphabet, nullptr, params); -} - /** * @brief Checks inclusion of languages of two NFAs: @p smaller and @p bigger (smaller <= bigger). * diff --git a/src/nfa/universal.cc b/src/nfa/universal.cc index 567e5bc0a..5a6c2cce9 100644 --- a/src/nfa/universal.cc +++ b/src/nfa/universal.cc @@ -144,14 +144,8 @@ bool mata::nfa::algorithms::is_universal_antichains( return true; } // }}} -// The dispatching method that calls the correct one based on parameters -bool mata::nfa::is_universal( - const Nfa& aut, - const Alphabet& alphabet, - Run* cex, - const ParameterMap& params) -{ // {{{ - +// The dispatching method that calls the correct one based on parameters. +bool mata::nfa::Nfa::is_universal(const Alphabet& alphabet, Run* cex, const ParameterMap& params) const { // setting the default algorithm decltype(algorithms::is_universal_naive)* algo = algorithms::is_universal_naive; if (!haskey(params, "algorithm")) { @@ -168,6 +162,9 @@ bool mata::nfa::is_universal( throw std::runtime_error(std::to_string(__func__) + " received an unknown value of the \"algo\" key: " + str_algo); } + return algo(*this, alphabet, cex); +} // is_universal() - return algo(aut, alphabet, cex); -} // is_universal }}} +bool mata::nfa::Nfa::is_universal(const Alphabet& alphabet, const ParameterMap& params) const { + return this->is_universal(alphabet, nullptr, params); +} diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 9121c344f..4977cc429 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -1073,7 +1073,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, params); + bool is_univ = aut.is_universal(alph, params); REQUIRE(!is_univ); } @@ -1087,7 +1087,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, &cex, params); + bool is_univ = aut.is_universal(alph, &cex, params); REQUIRE(is_univ); REQUIRE(cex.word.empty()); @@ -1102,7 +1102,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, &cex, params); + bool is_univ = aut.is_universal(alph, &cex, params); REQUIRE(!is_univ); REQUIRE(((cex.word == Word{alph["a"]}) || (cex.word == Word{alph["b"]}))); @@ -1121,7 +1121,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, params); + bool is_univ = aut.is_universal(alph, params); REQUIRE(!is_univ); } @@ -1138,7 +1138,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, params); + bool is_univ = aut.is_universal(alph, params); REQUIRE(!is_univ); } @@ -1155,7 +1155,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, params); + bool is_univ = aut.is_universal(alph, params); REQUIRE(is_univ); } @@ -1180,7 +1180,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, &cex, params); + bool is_univ = aut.is_universal(alph, &cex, params); REQUIRE(!is_univ); @@ -1208,7 +1208,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, &cex, params); + bool is_univ = aut.is_universal(alph, &cex, params); REQUIRE(is_univ); } @@ -1232,7 +1232,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, &cex, params); + bool is_univ = aut.is_universal(alph, &cex, params); REQUIRE(is_univ); } @@ -1248,7 +1248,7 @@ TEST_CASE("mata::nfa::is_universal()") for (const auto& algo : ALGORITHMS) { params["algorithm"] = algo; - bool is_univ = is_universal(aut, alph, &cex, params); + bool is_univ = aut.is_universal(alph, &cex, params); REQUIRE(is_univ); } @@ -1258,7 +1258,7 @@ TEST_CASE("mata::nfa::is_universal()") { OnTheFlyAlphabet alph{}; - CHECK_THROWS_WITH(is_universal(aut, alph, params), + CHECK_THROWS_WITH(aut.is_universal(alph, params), Catch::Contains("requires setting the \"algo\" key")); } @@ -1267,7 +1267,7 @@ TEST_CASE("mata::nfa::is_universal()") OnTheFlyAlphabet alph{}; params["algorithm"] = "foo"; - CHECK_THROWS_WITH(is_universal(aut, alph, params), + CHECK_THROWS_WITH(aut.is_universal(alph, params), Catch::Contains("received an unknown value")); } } // }}} diff --git a/tests/re2parser.cc b/tests/re2parser.cc index a3d28afc3..88b690f81 100644 --- a/tests/re2parser.cc +++ b/tests/re2parser.cc @@ -55,7 +55,7 @@ TEST_CASE("mata::Parser basic_parsing") { REQUIRE(is_in_lang(aut, Word{0x7f})); REQUIRE(is_in_lang(aut, Word{})); OnTheFlyAlphabet alph{}; - REQUIRE(is_universal(aut,alph)); + REQUIRE(aut.is_universal(alph)); } SECTION("Special character") { From 69c2215e2fe5a0ff1012388d412e6c3a740a82e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 11 Sep 2023 12:05:11 +0200 Subject: [PATCH 19/23] Move 'is_in_lang()' checks to 'Nfa' --- bindings/python/libmata/nfa/nfa.pxd | 4 +- bindings/python/libmata/nfa/nfa.pyx | 42 +- bindings/python/tests/test_nfa.py | 44 +- bindings/python/tests/test_regex.py | 12 +- .../notebooks/example-02-redos-attacks.ipynb | 10 +- include/mata/nfa/nfa.hh | 15 +- src/nfa/operations.cc | 36 +- tests/nfa/nfa-concatenation.cc | 12 +- tests/nfa/nfa.cc | 140 +- tests/re2parser.cc | 1561 ++++++++--------- tests/strings/nfa-string-solving.cc | 10 +- 11 files changed, 937 insertions(+), 949 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 540b6e378..273c6b51e 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -172,14 +172,14 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": bool is_complete(CAlphabet*) except + bool is_complete() except + bool is_universal(CAlphabet&, ParameterMap&) except + + bool is_in_lang(CRun&) + bool is_prfx_in_lang(CRun&) # Automata tests cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CRun*, CAlphabet*, ParameterMap&) except + cdef bool c_are_equivalent "mata::nfa::are_equivalent" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) cdef bool c_are_equivalent "mata::nfa::are_equivalent" (CNfa&, CNfa&, ParameterMap&) - cdef bool c_is_in_lang "mata::nfa::is_in_lang" (CNfa&, CRun&) - cdef bool c_is_prfx_in_lang "mata::nfa::is_prfx_in_lang" (CNfa&, CRun&) # Automata operations cdef void compute_fw_direct_simulation(const CNfa&) diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index 60314b3ff..b9c5b6e65 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -726,6 +726,26 @@ cdef class Nfa: } ) + def is_in_lang(self, vector[Symbol] word): + """Tests if word is in language. + + :param vector[Symbol] word: tested word. + :return: true if word is in language of the NFA. + """ + run = Run() + run.thisptr.word = word + return self.thisptr.get().is_in_lang(dereference(run.thisptr)) + + def is_prefix_in_lang(self, vector[Symbol] word): + """Test if any prefix of the word is in the language. + + :param vector[Symbol] word: tested word + :return: true if any prefix of word is in language of the NFA. + """ + run = Run() + run.thisptr.word = word + return self.thisptr.get().is_prfx_in_lang(dereference(run.thisptr)) + def get_symbols(self): """Return a set of symbols used on the transitions in NFA. @@ -1066,28 +1086,6 @@ def equivalence_check(Nfa lhs, Nfa rhs, alph.Alphabet alphabet = None, params = } ) -def is_in_lang(Nfa lhs, vector[Symbol] word): - """Tests if word is in language - - :param Nfa lhs: tested automaton - :param vector[Symbol] word: tested word - :return: true if word is in language of automaton lhs - """ - run = Run() - run.thisptr.word = word - return mata_nfa.c_is_in_lang(dereference(lhs.thisptr.get()), dereference(run.thisptr)) - -def is_prefix_in_lang(Nfa lhs, vector[Symbol] word): - """Test if any prefix of the word is in the language - - :param Nfa lhs: tested automaton - :param vector[Symbol] word: tested word - :return: true if any prefix of word is in language of automaton lhs - """ - run = Run() - run.thisptr.word = word - return mata_nfa.c_is_prfx_in_lang(dereference(lhs.thisptr.get()), dereference(run.thisptr)) - def accepts_epsilon(Nfa lhs): """Tests if automaton accepts epsilon diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index 2e520db65..43df04571 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -388,11 +388,11 @@ def test_completeness( def test_in_language( fa_one_divisible_by_two, fa_one_divisible_by_four, fa_one_divisible_by_eight ): - assert mata_nfa.is_in_lang(fa_one_divisible_by_two, [1, 1]) - assert not mata_nfa.is_in_lang(fa_one_divisible_by_two, [1, 1, 1]) + assert fa_one_divisible_by_two.is_in_lang([1, 1]) + assert not fa_one_divisible_by_two.is_in_lang([1, 1, 1]) - assert mata_nfa.is_prefix_in_lang(fa_one_divisible_by_four, [1, 1, 1, 1, 0]) - assert not mata_nfa.is_prefix_in_lang(fa_one_divisible_by_four, [1, 1, 1, 0, 0]) + assert fa_one_divisible_by_four.is_prefix_in_lang([1, 1, 1, 1, 0]) + assert not fa_one_divisible_by_four.is_prefix_in_lang([1, 1, 1, 0, 0]) assert not mata_nfa.accepts_epsilon(fa_one_divisible_by_four) lhs = mata_nfa.Nfa(2) @@ -413,13 +413,13 @@ def test_union( alph.translate_symbol("a") alph.translate_symbol("b") - assert mata_nfa.is_in_lang(fa_one_divisible_by_two, [1, 1]) - assert not mata_nfa.is_in_lang(fa_one_divisible_by_four, [1, 1]) + assert fa_one_divisible_by_two.is_in_lang([1, 1]) + assert not fa_one_divisible_by_four.is_in_lang([1, 1]) uni = mata_nfa.union(fa_one_divisible_by_two, fa_one_divisible_by_four) - assert mata_nfa.is_in_lang(uni, [1, 1]) - assert mata_nfa.is_in_lang(uni, [1, 1, 1, 1]) - assert mata_nfa.is_in_lang(uni, [1, 1, 1, 1, 1, 1]) - assert mata_nfa.is_in_lang(uni, [1, 1, 1, 1, 1, 1, 1, 1, ]) + assert uni.is_in_lang([1, 1]) + assert uni.is_in_lang([1, 1, 1, 1]) + assert uni.is_in_lang([1, 1, 1, 1, 1, 1]) + assert uni.is_in_lang([1, 1, 1, 1, 1, 1, 1, 1, ]) assert mata_nfa.is_included(fa_one_divisible_by_two, uni, alph) assert mata_nfa.is_included(fa_one_divisible_by_four, uni, alph) @@ -436,10 +436,10 @@ def test_intersection( inter, product_map = mata_nfa.intersection_with_product_map(fa_one_divisible_by_two, fa_one_divisible_by_four) - assert not mata_nfa.is_in_lang(inter, [1, 1]) - assert mata_nfa.is_in_lang(inter, [1, 1, 1, 1]) - assert not mata_nfa.is_in_lang(inter, [1, 1, 1, 1, 1, 1]) - assert mata_nfa.is_in_lang(inter, [1, 1, 1, 1, 1, 1, 1, 1, ]) + assert not inter.is_in_lang([1, 1]) + assert inter.is_in_lang([1, 1, 1, 1]) + assert not inter.is_in_lang([1, 1, 1, 1, 1, 1]) + assert inter.is_in_lang([1, 1, 1, 1, 1, 1, 1, 1, ]) assert mata_nfa.is_included(inter, fa_one_divisible_by_two, alph) assert mata_nfa.is_included(inter, fa_one_divisible_by_four, alph) assert mata_nfa.is_included(inter, fa_one_divisible_by_two) @@ -552,9 +552,9 @@ def test_complement( alph.translate_symbol("b") res = mata_nfa.complement(fa_one_divisible_by_two, alph) - assert not mata_nfa.is_in_lang(res, [1, 1]) - assert mata_nfa.is_in_lang(res, [1, 1, 1]) - assert not mata_nfa.is_in_lang(res, [1, 1, 1, 1]) + assert not res.is_in_lang([1, 1]) + assert res.is_in_lang([1, 1, 1]) + assert not res.is_in_lang([1, 1, 1, 1]) def test_revert(): @@ -563,12 +563,12 @@ def test_revert(): lhs.add_transition(0, 0, 1) lhs.add_transition(1, 1, 2) lhs.make_final_state(2) - assert mata_nfa.is_in_lang(lhs, [0, 1]) - assert not mata_nfa.is_in_lang(lhs, [1, 0]) + assert lhs.is_in_lang([0, 1]) + assert not lhs.is_in_lang([1, 0]) rhs = mata_nfa.revert(lhs) - assert not mata_nfa.is_in_lang(rhs, [0, 1]) - assert mata_nfa.is_in_lang(rhs, [1, 0]) + assert not rhs.is_in_lang([0, 1]) + assert rhs.is_in_lang([1, 0]) def test_removing_epsilon(): @@ -659,7 +659,7 @@ def test_trim(prepare_automaton_a): assert len(nfa.final_states) == len(old_nfa.final_states) for word in mata_strings.get_shortest_words(old_nfa): - assert mata_nfa.is_in_lang(nfa, word) + assert nfa.is_in_lang(word) nfa.remove_final_state(2) # '2' is the new final state in the earlier trimmed automaton. nfa.trim() diff --git a/bindings/python/tests/test_regex.py b/bindings/python/tests/test_regex.py index 76cd75524..35fcd0229 100644 --- a/bindings/python/tests/test_regex.py +++ b/bindings/python/tests/test_regex.py @@ -12,14 +12,14 @@ def test_regex(): rhs = parser.from_regex("b|c") union = mata_nfa.union(lhs, rhs) - assert mata_nfa.is_in_lang(union, mata_nfa.encode_word(alphabet, "a")) - assert mata_nfa.is_in_lang(union, mata_nfa.encode_word(alphabet, "b")) - assert mata_nfa.is_in_lang(union, mata_nfa.encode_word(alphabet, "c")) + assert union.is_in_lang(mata_nfa.encode_word(alphabet, "a")) + assert union.is_in_lang(mata_nfa.encode_word(alphabet, "b")) + assert union.is_in_lang(mata_nfa.encode_word(alphabet, "c")) intersection = mata_nfa.intersection(lhs, rhs) - assert not mata_nfa.is_in_lang(intersection, mata_nfa.encode_word(alphabet, "a")) - assert mata_nfa.is_in_lang(intersection, mata_nfa.encode_word(alphabet, "b")) - assert not mata_nfa.is_in_lang(intersection, mata_nfa.encode_word(alphabet, "c")) + assert not intersection.is_in_lang(mata_nfa.encode_word(alphabet, "a")) + assert intersection.is_in_lang(mata_nfa.encode_word(alphabet, "b")) + assert not intersection.is_in_lang(mata_nfa.encode_word(alphabet, "c")) def test_stars_concatenation(): diff --git a/examples/notebooks/example-02-redos-attacks.ipynb b/examples/notebooks/example-02-redos-attacks.ipynb index edb843972..f1461cbff 100644 --- a/examples/notebooks/example-02-redos-attacks.ipynb +++ b/examples/notebooks/example-02-redos-attacks.ipynb @@ -113,7 +113,7 @@ } ], "source": [ - "mata_nfa.is_in_lang(lhs, translate_string(\"test@gmail.com\"))" + "lhs.is_in_lang(translate_string(\"test@gmail.com\"))" ] }, { @@ -134,7 +134,7 @@ } ], "source": [ - "timeit.timeit(lambda: mata_nfa.is_in_lang(lhs, translate_string(\"test@gmail.com\")))" + "timeit.timeit(lambda: lhs.is_in_lang(translate_string(\"test@gmail.com\")))" ] }, { @@ -165,7 +165,7 @@ } ], "source": [ - "mata_nfa.is_in_lang(lhs, translate_string(\"testtgmaillcom\"))" + "lhs.is_in_lang(translate_string(\"testtgmaillcom\"))" ] }, { @@ -186,7 +186,7 @@ } ], "source": [ - "timeit.timeit(lambda: mata_nfa.is_in_lang(lhs, translate_string(\"testtgmaillcom\")))" + "timeit.timeit(lambda: lhs.is_in_lang(translate_string(\"testtgmaillcom\")))" ] }, { @@ -210,7 +210,7 @@ "dataset = {'time': [], 'size': []}\n", "for i in range(0, 1000):\n", " workload = \"testtgmaillcom\" + \"a\"*i\n", - " time = timeit.timeit(lambda: mata_nfa.is_in_lang(lhs, translate_string(workload)), number=10)\n", + " time = timeit.timeit(lambda: lhs.is_in_lang(translate_string(workload)), number=10)\n", " if float(time):\n", " dataset['time'].append(float(time))\n", " dataset['size'].append(len(workload))\n", diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 573ef07d8..ca1cf2e60 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -292,6 +292,15 @@ public: const ParameterMap& params = {{ "algorithm", "antichains" }}) const; /// Is the language of the automaton universal? bool is_universal(const Alphabet& alphabet, const ParameterMap& params) const; + + /// Checks whether a word is in the language of an automaton. + bool is_in_lang(const Run& word) const; + /// Checks whether a word is in the language of an automaton. + bool is_in_lang(const Word& word) { return is_in_lang(Run{ word, {} }); } + + /// Checks whether the prefix of a string is in the language of an automaton + bool is_prfx_in_lang(const Run& word) const; + }; // struct Nfa. // Allow variadic number of arguments of the same type. @@ -580,12 +589,6 @@ Nfa remove_epsilon(const Nfa& aut, Symbol epsilon = EPSILON); std::pair get_word_for_path(const Nfa& aut, const Run& run); -/// Checks whether a string is in the language of an automaton -bool is_in_lang(const Nfa& aut, const Run& word); - -/// Checks whether the prefix of a string is in the language of an automaton -bool is_prfx_in_lang(const Nfa& aut, const Run& word); - /** Encodes a vector of strings (each corresponding to one symbol) into a * @c Word instance */ diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index c87b996c6..1809297cb 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -508,33 +508,25 @@ std::pair mata::nfa::get_word_for_path(const Nfa& aut, const Run& run } //TODO: this is not efficient -bool mata::nfa::is_in_lang(const Nfa& aut, const Run& run) -{ - StateSet cur(aut.initial); - - for (Symbol sym : run.word) - { - cur = aut.post(cur, sym); - if (cur.empty()) { return false; } +bool mata::nfa::Nfa::is_in_lang(const Run& run) const { + StateSet current_post(this->initial); + for (const Symbol sym : run.word) { + current_post = this->post(current_post, sym); + if (current_post.empty()) { return false; } } - - return aut.final.intersects_with(cur); + return this->final.intersects_with(current_post); } /// Checks whether the prefix of a string is in the language of an automaton // TODO: slow and it should share code with is_in_lang -bool mata::nfa::is_prfx_in_lang(const Nfa& aut, const Run& run) -{ - StateSet cur = StateSet{ aut.initial }; - - for (Symbol sym : run.word) - { - if (aut.final.intersects_with(cur)) { return true; } - cur = aut.post(cur, sym); - if (cur.empty()) { return false; } - } - - return aut.final.intersects_with(cur); +bool mata::nfa::Nfa::is_prfx_in_lang(const Run& run) const { + StateSet current_post{ this->initial }; + for (const Symbol sym : run.word) { + if (this->final.intersects_with(current_post)) { return true; } + current_post = this->post(current_post, sym); + if (current_post.empty()) { return false; } + } + return this->final.intersects_with(current_post); } bool mata::nfa::Nfa::is_lang_empty(Run* cex) const { diff --git a/tests/nfa/nfa-concatenation.cc b/tests/nfa/nfa-concatenation.cc index a744643f4..fdeabf6ae 100644 --- a/tests/nfa/nfa-concatenation.cc +++ b/tests/nfa/nfa-concatenation.cc @@ -208,7 +208,7 @@ TEST_CASE("mata::nfa::concatenate()") { result = concatenate(lhs, rhs); CHECK(!result.is_lang_empty()); - CHECK(is_in_lang(result, Run{ {}, {} })); + CHECK(result.is_in_lang(Run{ {}, {} })); CHECK(result.delta.empty()); } @@ -291,11 +291,11 @@ TEST_CASE("mata::nfa::concatenate()") { rhs.delta.add(0, 'a', 0); result = concatenate(lhs, rhs); - CHECK(is_in_lang(result, Run{ { 'b' }, {} })); - CHECK(is_in_lang(result, Run{ { 'b', 'a' }, {} })); - CHECK(is_in_lang(result, Run{ { 'b', 'a', 'a' }, {} })); - CHECK(!is_in_lang(result, Run{ { 'a' }, {} })); - CHECK(!is_in_lang(result, Run{ { 'a', 'b' }, {} })); + CHECK(result.is_in_lang(Run{ { 'b' }, {} })); + CHECK(result.is_in_lang(Run{ { 'b', 'a' }, {} })); + CHECK(result.is_in_lang(Run{ { 'b', 'a', 'a' }, {} })); + CHECK(!result.is_in_lang(Run{ { 'a' }, {} })); + CHECK(!result.is_in_lang(Run{ { 'a', 'b' }, {} })); auto shortest_words{ get_shortest_words(result) }; CHECK(shortest_words.size() == 1); CHECK(shortest_words.find(std::vector{ 'b' }) != shortest_words.end()); diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 4977cc429..2be5e43a7 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -520,7 +520,7 @@ TEST_CASE("mata::nfa::construct() correct calls") REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word == encode_word(&alphabet, { "a"}).word); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "a"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "a"}))); } SECTION("construct a more complicated non-empty automaton") @@ -547,14 +547,14 @@ TEST_CASE("mata::nfa::construct() correct calls") aut = builder::construct(parsec, &alphabet); // some samples - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "b", "a"}))); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "a", "c", "a", "a"}))); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "b", "a"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "a", "c", "a", "a"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, {"a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"}))); // some wrong samples - REQUIRE(!is_in_lang(aut, encode_word(&alphabet, { "b", "c"}))); - REQUIRE(!is_in_lang(aut, encode_word(&alphabet, { "a", "c", "c", "a"}))); - REQUIRE(!is_in_lang(aut, encode_word(&alphabet, { "b", "a", "c", "b"}))); + REQUIRE(!aut.is_in_lang(encode_word(&alphabet, { "b", "c"}))); + REQUIRE(!aut.is_in_lang(encode_word(&alphabet, { "a", "c", "c", "a"}))); + REQUIRE(!aut.is_in_lang(encode_word(&alphabet, { "b", "a", "c", "b"}))); } } // }}} @@ -691,7 +691,7 @@ TEST_CASE("mata::nfa::construct() from IntermediateAut correct calls") REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word == encode_word(&alphabet, { "a" }).word); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "a" }))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "a" }))); } SECTION("construct a more complicated non-empty automaton from intermediate automaton") @@ -723,14 +723,14 @@ TEST_CASE("mata::nfa::construct() from IntermediateAut correct calls") plumbing::construct(&aut, inter_aut, &alphabet); // some samples - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "b", "a"}))); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "a", "c", "a", "a"}))); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "b", "a"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "a", "c", "a", "a"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, {"a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"}))); // some wrong samples - REQUIRE(!is_in_lang(aut, encode_word(&alphabet, { "b", "c"}))); - REQUIRE(!is_in_lang(aut, encode_word(&alphabet, { "a", "c", "c", "a"}))); - REQUIRE(!is_in_lang(aut, encode_word(&alphabet, { "b", "a", "c", "b"}))); + REQUIRE(!aut.is_in_lang(encode_word(&alphabet, { "b", "c"}))); + REQUIRE(!aut.is_in_lang(encode_word(&alphabet, { "a", "c", "c", "a"}))); + REQUIRE(!aut.is_in_lang(encode_word(&alphabet, { "b", "a", "c", "b"}))); } SECTION("construct - final states from negation") @@ -753,10 +753,10 @@ TEST_CASE("mata::nfa::construct() from IntermediateAut correct calls") plumbing::construct(&aut, inter_aut, &alphabet); REQUIRE(aut.final.size() == 4); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "a1", "a2"}))); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "a1", "a2", "a3"}))); - REQUIRE(!is_in_lang(aut, encode_word(&alphabet, { "a1", "a2", "a3", "a4"}))); - REQUIRE(is_in_lang(aut, encode_word(&alphabet, { "a1", "a2", "a3", "a5", "a7"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "a1", "a2"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "a1", "a2", "a3"}))); + REQUIRE(!aut.is_in_lang(encode_word(&alphabet, { "a1", "a2", "a3", "a4"}))); + REQUIRE(aut.is_in_lang(encode_word(&alphabet, { "a1", "a2", "a3", "a5", "a7"}))); } SECTION("construct - final states given as true") @@ -937,11 +937,11 @@ TEST_CASE("mata::nfa::complement()") cmpl = complement(aut, alph, {{"algorithm", "classical"}, {"minimize", "false"}}); - REQUIRE(is_in_lang(cmpl, {})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"] }, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["b"] }, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"], alph["a"]}, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"], alph["b"], alph["b"], alph["a"] }, {}})); + REQUIRE(cmpl.is_in_lang({})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"] }, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["b"] }, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"], alph["a"]}, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"], alph["b"], alph["b"], alph["a"] }, {}})); Nfa sigma_star_nfa{ nfa::builder::create_sigma_star_nfa(&alph) }; CHECK(are_equivalent(cmpl, sigma_star_nfa)); @@ -968,11 +968,11 @@ TEST_CASE("mata::nfa::complement()") cmpl = complement(aut, alph, {{"algorithm", "classical"}, {"minimize", "false"}}); - REQUIRE(!is_in_lang(cmpl, { })); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"]}, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["b"]}, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"], alph["a"]}, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"], alph["b"], alph["b"], alph["a"]}, {}})); + REQUIRE(!cmpl.is_in_lang({})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"]}, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["b"]}, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"], alph["a"]}, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"], alph["b"], alph["b"], alph["a"]}, {}})); REQUIRE(cmpl.initial.size() == 1); REQUIRE(cmpl.final.size() == 1); REQUIRE(cmpl.delta.num_of_transitions() == 4); @@ -991,13 +991,13 @@ TEST_CASE("mata::nfa::complement()") cmpl = complement(aut, alph, {{"algorithm", "classical"}, {"minimize", "false"}}); - REQUIRE(!is_in_lang(cmpl, { })); - REQUIRE(!is_in_lang(cmpl, {{ alph["a"] }, {}})); - REQUIRE(!is_in_lang(cmpl, {{ alph["b"] }, {}})); - REQUIRE(!is_in_lang(cmpl, {{ alph["a"], alph["a"] }, {}})); - REQUIRE(is_in_lang(cmpl, {{ alph["a"], alph["b"], alph["b"], alph["a"] }, {}})); - REQUIRE(!is_in_lang(cmpl, {{ alph["a"], alph["a"], alph["b"], alph["b"] }, {}})); - REQUIRE(is_in_lang(cmpl, {{ alph["b"], alph["a"], alph["a"], alph["a"] }, {}})); + REQUIRE(!cmpl.is_in_lang(Word{})); + REQUIRE(!cmpl.is_in_lang(Word{ alph["a"] })); + REQUIRE(!cmpl.is_in_lang(Word{ alph["b"] })); + REQUIRE(!cmpl.is_in_lang(Word{ alph["a"], alph["a"] })); + REQUIRE(cmpl.is_in_lang(Word{ alph["a"], alph["b"], alph["b"], alph["a"] })); + REQUIRE(!cmpl.is_in_lang(Word{ alph["a"], alph["a"], alph["b"], alph["b"] })); + REQUIRE(cmpl.is_in_lang(Word{ alph["b"], alph["a"], alph["a"], alph["a"] })); REQUIRE(cmpl.initial.size() == 1); REQUIRE(cmpl.final.size() == 1); @@ -1021,11 +1021,11 @@ TEST_CASE("mata::nfa::complement()") cmpl = complement(aut, alph, {{"algorithm", "classical"}, {"minimize", "true"}}); - REQUIRE(is_in_lang(cmpl, {})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"] }, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["b"] }, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"], alph["a"]}, {}})); - REQUIRE(is_in_lang(cmpl, Run{{ alph["a"], alph["b"], alph["b"], alph["a"] }, {}})); + REQUIRE(cmpl.is_in_lang({})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"] }, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["b"] }, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"], alph["a"]}, {}})); + REQUIRE(cmpl.is_in_lang(Run{{ alph["a"], alph["b"], alph["b"], alph["a"] }, {}})); Nfa sigma_star_nfa{ nfa::builder::create_sigma_star_nfa(&alph) }; CHECK(are_equivalent(sigma_star_nfa, cmpl)); @@ -1886,10 +1886,10 @@ TEST_CASE("mata::nfa::is_prfx_in_lang()") { Run w; w.word = {'a', 'b', 'd'}; - REQUIRE(!is_prfx_in_lang(aut, w)); + REQUIRE(!aut.is_prfx_in_lang(w)); w.word = { }; - REQUIRE(!is_prfx_in_lang(aut, w)); + REQUIRE(!aut.is_prfx_in_lang(w)); } SECTION("automaton accepting only epsilon") @@ -1899,10 +1899,10 @@ TEST_CASE("mata::nfa::is_prfx_in_lang()") Run w; w.word = { }; - REQUIRE(is_prfx_in_lang(aut, w)); + REQUIRE(aut.is_prfx_in_lang(w)); w.word = {'a', 'b'}; - REQUIRE(is_prfx_in_lang(aut, w)); + REQUIRE(aut.is_prfx_in_lang(w)); } SECTION("small automaton") @@ -1911,28 +1911,28 @@ TEST_CASE("mata::nfa::is_prfx_in_lang()") Run w; w.word = {'b', 'a'}; - REQUIRE(is_prfx_in_lang(aut, w)); + REQUIRE(aut.is_prfx_in_lang(w)); w.word = { }; - REQUIRE(!is_prfx_in_lang(aut, w)); + REQUIRE(!aut.is_prfx_in_lang(w)); w.word = {'c', 'b', 'a'}; - REQUIRE(!is_prfx_in_lang(aut, w)); + REQUIRE(!aut.is_prfx_in_lang(w)); w.word = {'c', 'b', 'a', 'a'}; - REQUIRE(is_prfx_in_lang(aut, w)); + REQUIRE(aut.is_prfx_in_lang(w)); w.word = {'a', 'a'}; - REQUIRE(is_prfx_in_lang(aut, w)); + REQUIRE(aut.is_prfx_in_lang(w)); w.word = {'c', 'b', 'b', 'a', 'c', 'b'}; - REQUIRE(is_prfx_in_lang(aut, w)); + REQUIRE(aut.is_prfx_in_lang(w)); w.word = Word(100000, 'a'); - REQUIRE(is_prfx_in_lang(aut, w)); + REQUIRE(aut.is_prfx_in_lang(w)); w.word = Word(100000, 'b'); - REQUIRE(!is_prfx_in_lang(aut, w)); + REQUIRE(!aut.is_prfx_in_lang(w)); } } // }}} @@ -2113,20 +2113,20 @@ TEST_CASE("mata::nfa::union_norename()") { lhs.initial.insert(0); lhs.delta.add(0, 0, 1); lhs.final.insert(1); - REQUIRE(!is_in_lang(lhs, one)); - REQUIRE(is_in_lang(lhs, zero)); + REQUIRE(!lhs.is_in_lang(one)); + REQUIRE(lhs.is_in_lang(zero)); Nfa rhs(2); rhs.initial.insert(0); rhs.delta.add(0, 1, 1); rhs.final.insert(1); - REQUIRE(is_in_lang(rhs, one)); - REQUIRE(!is_in_lang(rhs, zero)); + REQUIRE(rhs.is_in_lang(one)); + REQUIRE(!rhs.is_in_lang(zero)); SECTION("failing minimal scenario") { Nfa result = uni(lhs, rhs); - REQUIRE(is_in_lang(result, one)); - REQUIRE(is_in_lang(result, zero)); + REQUIRE(result.is_in_lang(one)); + REQUIRE(result.is_in_lang(zero)); } } @@ -2378,7 +2378,7 @@ TEST_CASE("mata::nfa::trim()") CHECK(aut.num_of_states() == 4); for (const Word& word: get_shortest_words(orig_aut)) { - CHECK(is_in_lang(aut, Run{word,{}})); + CHECK(aut.is_in_lang(Run{word,{}})); } aut.final.erase(2); // '2' is the new final state in the earlier trimmed automaton. @@ -2396,7 +2396,7 @@ TEST_CASE("mata::nfa::trim()") CHECK(aut.num_of_states() == 4); for (const Word& word: get_shortest_words(orig_aut)) { - CHECK(is_in_lang(aut, Run{word,{}})); + CHECK(aut.is_in_lang(Run{word,{}})); } REQUIRE(state_map.size() == 4); CHECK(state_map.at(1) == 0); @@ -2669,20 +2669,20 @@ TEST_CASE("A segmentation fault in the make_complement") { TEST_CASE("mata::nfa:: create simple automata") { Nfa nfa{ builder::create_empty_string_nfa() }; - CHECK(is_in_lang(nfa, { {}, {} })); + CHECK(nfa.is_in_lang(Word{})); CHECK(get_word_lengths(nfa) == std::set>{ std::make_pair(0, 0) }); OnTheFlyAlphabet alphabet{ { "a", 0 }, { "b", 1 }, { "c", 2 } }; nfa = builder::create_sigma_star_nfa(&alphabet); - CHECK(is_in_lang(nfa, { {}, {} })); - CHECK(is_in_lang(nfa, { { 0 }, {} })); - CHECK(is_in_lang(nfa, { { 1 }, {} })); - CHECK(is_in_lang(nfa, { { 2 }, {} })); - CHECK(is_in_lang(nfa, { { 0, 1 }, {} })); - CHECK(is_in_lang(nfa, { { 1, 0 }, {} })); - CHECK(is_in_lang(nfa, { { 2, 2, 2 }, {} })); - CHECK(is_in_lang(nfa, { { 0, 1, 2, 2, 0, 1, 2, 1, 0, 0, 2, 1 }, {} })); - CHECK(!is_in_lang(nfa, { { 3 }, {} })); + CHECK(nfa.is_in_lang({ {}, {} })); + CHECK(nfa.is_in_lang({ 0 , {} })); + CHECK(nfa.is_in_lang({ 1 , {} })); + CHECK(nfa.is_in_lang({ 2 , {} })); + CHECK(nfa.is_in_lang({ { 0, 1 }, {} })); + CHECK(nfa.is_in_lang({ { 1, 0 }, {} })); + CHECK(nfa.is_in_lang({ { 2, 2, 2 }, {} })); + CHECK(nfa.is_in_lang({ { 0, 1, 2, 2, 0, 1, 2, 1, 0, 0, 2, 1 }, {} })); + CHECK(!nfa.is_in_lang({ 3 , {} })); } TEST_CASE("mata::nfa:: print_to_mata") { diff --git a/tests/re2parser.cc b/tests/re2parser.cc index 88b690f81..cd819e9fa 100644 --- a/tests/re2parser.cc +++ b/tests/re2parser.cc @@ -8,11 +8,6 @@ using Symbol = mata::Symbol; using Word = std::vector; using OnTheFlyAlphabet = mata::OnTheFlyAlphabet; -bool is_in_lang(const Nfa& aut, const Word& word) -{ - return is_in_lang(aut, Run{word, {}}); -} - // Some example regexes were taken from RegExr under GPL v3: https://github.com/gskinner/regexr. TEST_CASE("mata::Parser basic_parsing") { @@ -23,37 +18,37 @@ TEST_CASE("mata::Parser basic_parsing") { REQUIRE(aut.final.size() == aut.initial.size()); REQUIRE(aut.delta.empty()); REQUIRE(!aut.is_lang_empty()); - REQUIRE(is_in_lang(aut, Word{})); + REQUIRE(aut.is_in_lang(Word{})); } SECTION("Basic test") { mata::parser::create_nfa(&aut, "abcd"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.is_lang_empty()); - REQUIRE(!is_in_lang(aut, Word{'a','b','c'})); - REQUIRE(is_in_lang(aut, Word{'a','b','c','d'})); - REQUIRE(!is_in_lang(aut, Word{'a','b','c','d','d'})); - REQUIRE(!is_in_lang(aut, Word{'a','d','c'})); + REQUIRE(!aut.empty_language()); + REQUIRE(!aut.is_in_lang(Word{'a','b','c'})); + REQUIRE(aut.is_in_lang(Word{'a','b','c','d'})); + REQUIRE(!aut.is_in_lang(Word{'a','b','c','d','d'})); + REQUIRE(!aut.is_in_lang(Word{'a','d','c'})); } SECTION("Hex symbol encoding") { mata::parser::create_nfa(&aut, "\\x7f"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.is_lang_empty()); - REQUIRE(is_in_lang(aut, Word{127})); + REQUIRE(!aut.empty_language()); + REQUIRE(aut.is_in_lang(Word{127})); } SECTION("Wild cardinality") { mata::parser::create_nfa(&aut, ".*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.is_lang_empty()); - REQUIRE(is_in_lang(aut, Word{'w','h','a','t','e','v','e','r'})); - REQUIRE(is_in_lang(aut, Word{127})); - REQUIRE(is_in_lang(aut, Word{0x7f})); - REQUIRE(is_in_lang(aut, Word{})); + REQUIRE(!aut.empty_language()); + REQUIRE(aut.is_in_lang(Word{'w','h','a','t','e','v','e','r'})); + REQUIRE(aut.is_in_lang(Word{127})); + REQUIRE(aut.is_in_lang(Word{0x7f})); + REQUIRE(aut.is_in_lang(Word{})); OnTheFlyAlphabet alph{}; REQUIRE(aut.is_universal(alph)); } @@ -61,31 +56,31 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Special character") { mata::parser::create_nfa(&aut, "\\t"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{'\t'})); - CHECK(!is_in_lang(aut, Word{'t'})); - CHECK(!is_in_lang(aut, Word{})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{'\t'})); + CHECK(!aut.is_in_lang(Word{'t'})); + CHECK(!aut.is_in_lang(Word{})); } SECTION("Whitespace") { mata::parser::create_nfa(&aut, "a\\sb"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{'a', '\t', 'b'})); - CHECK(!is_in_lang(aut, Word{})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{'a', '\t', 'b'})); + CHECK(!aut.is_in_lang(Word{})); } SECTION("Iteration test") { mata::parser::create_nfa(&aut, "ab*cd*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.is_lang_empty()); - REQUIRE(is_in_lang(aut, Word{'a','b','c'})); - REQUIRE(is_in_lang(aut, Word{'a','b','c','d'})); - REQUIRE(is_in_lang(aut, Word{'a','c','d'})); - REQUIRE(is_in_lang(aut, Word{'a','b','b','c','d'})); - REQUIRE(is_in_lang(aut, Word{'a','b','c','d','d'})); - REQUIRE(!is_in_lang(aut, Word{'a','d','c'})); + REQUIRE(!aut.empty_language()); + REQUIRE(aut.is_in_lang(Word{'a','b','c'})); + REQUIRE(aut.is_in_lang(Word{'a','b','c','d'})); + REQUIRE(aut.is_in_lang(Word{'a','c','d'})); + REQUIRE(aut.is_in_lang(Word{'a','b','b','c','d'})); + REQUIRE(aut.is_in_lang(Word{'a','b','c','d','d'})); + REQUIRE(!aut.is_in_lang(Word{'a','d','c'})); } SECTION("Additional parenthesis") { @@ -140,830 +135,830 @@ TEST_CASE("mata::Parser basic_parsing") { } CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'a','b'})); - CHECK(is_in_lang(aut, Word{'a','a','b'})); - CHECK(!is_in_lang(aut, Word{'b','a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'a','b'})); + CHECK(aut.is_in_lang(Word{'a','a','b'})); + CHECK(!aut.is_in_lang(Word{'b','a'})); CHECK(are_equivalent(aut, expected)); } SECTION("Complex regex") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'e', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'e', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'e', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'e', 'b'})); } SECTION("Complex regex with additional plus") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'e', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'e', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Reduced complex regex with additional plus") { mata::parser::create_nfa(&aut, "(e)(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'e', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'e', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Reduced complex regex with additional plus 2") { mata::parser::create_nfa(&aut, "(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'w'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'w'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Reduced complex regex with additional plus 2.5") { mata::parser::create_nfa(&aut, "(w*)(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'w'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'w'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Reduced complex regex with additional plus 2.63") { mata::parser::create_nfa(&aut, "w*b+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'w'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'w'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Reduced complex regex with additional plus 2.75") { mata::parser::create_nfa(&aut, "w(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b'})); - CHECK(!is_in_lang(aut, Word{'w', 'w', 'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'w'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b'})); + CHECK(!aut.is_in_lang(Word{'w', 'w', 'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'w'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Reduced complex regex with additional plus 2.85") { mata::parser::create_nfa(&aut, "w*(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'w'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'w'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Reduced complex regex with additional plus 3") { mata::parser::create_nfa(&aut, "(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Complex regex 2") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)(b*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'e', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w'})); - CHECK(is_in_lang(aut, Word{'e', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'e', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w'})); + CHECK(aut.is_in_lang(Word{'e', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("Complex regex 2 with additional plus") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)+(b*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'e', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w'})); - CHECK(is_in_lang(aut, Word{'e', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'e', 'w', 'w', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'w', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'e', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w'})); + CHECK(aut.is_in_lang(Word{'e', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'e', 'w', 'w', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'w', 'b'})); } SECTION("a+b+") { mata::parser::create_nfa(&aut, "a+b+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'a', 'a', 'b', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'a', 'a', 'b', 'a'})); } SECTION("a+b+a*") { mata::parser::create_nfa(&aut, "a+b+a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a', 'a'})); } SECTION("a+(b+)a*") { mata::parser::create_nfa(&aut, "a+(b+)a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a', 'a'})); } SECTION("(a+(b+)a*)") { mata::parser::create_nfa(&aut, "(a+(b+)a*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a', 'a'})); } SECTION("(a+b*a*)") { mata::parser::create_nfa(&aut, "(a+b*a*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b', 'b', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b', 'b', 'a', 'a'})); } SECTION("a+a+") { mata::parser::create_nfa(&aut, "a+a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'a'})); } SECTION("(a+)a+") { mata::parser::create_nfa(&aut, "(a+)a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'a'})); } SECTION("a(a+)") { mata::parser::create_nfa(&aut, "a(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'a'})); } SECTION("(a+)b") { mata::parser::create_nfa(&aut, "(a+)b"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a', 'b'})); } SECTION("b(a+)") { mata::parser::create_nfa(&aut, "b(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'a', 'a', 'a'})); } SECTION("b|(a+)") { mata::parser::create_nfa(&aut, "b|(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'a'})); - CHECK(!is_in_lang(aut, Word{'b', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'a'})); + CHECK(!aut.is_in_lang(Word{'b', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a'})); } SECTION("b|a+") { mata::parser::create_nfa(&aut, "b|a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'a'})); - CHECK(!is_in_lang(aut, Word{'b', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'a'})); + CHECK(!aut.is_in_lang(Word{'b', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a'})); } SECTION("b|a") { mata::parser::create_nfa(&aut, "b|a"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'a'})); - CHECK(!is_in_lang(aut, Word{'b', 'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'a'})); + CHECK(!aut.is_in_lang(Word{'b', 'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a', 'a'})); } SECTION("b|a*") { mata::parser::create_nfa(&aut, "b|a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'a'})); - CHECK(!is_in_lang(aut, Word{'b', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'a'})); + CHECK(!aut.is_in_lang(Word{'b', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'a'})); } SECTION("bba+") { mata::parser::create_nfa(&aut, "bba+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'b', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b', 'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b', 'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'b', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b', 'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b', 'a', 'a', 'a'})); } SECTION("b*ba+") { mata::parser::create_nfa(&aut, "b*ba+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'b', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b', 'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b', 'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'b', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b', 'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b', 'a', 'a', 'a'})); } SECTION("b*ca+") { mata::parser::create_nfa(&aut, "b*ca+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b', 'c', 'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'c', 'a', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b', 'c', 'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'c', 'a', 'a', 'a'})); } SECTION("[abcd]") { mata::parser::create_nfa(&aut, "[abcd]"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'d'})); - CHECK(!is_in_lang(aut, Word{'b', 'b'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'d'})); + CHECK(!aut.is_in_lang(Word{'b', 'b'})); } SECTION("[abcd]*") { mata::parser::create_nfa(&aut, "[abcd]*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'d'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'d'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c'})); } SECTION("[abcd]*e*") { mata::parser::create_nfa(&aut, "[abcd]*e*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'d'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c'})); - - CHECK(is_in_lang(aut, Word{'a', 'e'})); - CHECK(is_in_lang(aut, Word{'d', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e', 'e'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'d'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c'})); + + CHECK(aut.is_in_lang(Word{'a', 'e'})); + CHECK(aut.is_in_lang(Word{'d', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e', 'e'})); } SECTION("[abcd]*e+") { mata::parser::create_nfa(&aut, "[abcd]*e+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'d'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'b', 'b'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'d', 'd'})); - CHECK(!is_in_lang(aut, Word{'a', 'd'})); - CHECK(!is_in_lang(aut, Word{'a', 'd', 'c'})); - - CHECK(is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'a', 'e'})); - CHECK(is_in_lang(aut, Word{'d', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e', 'e'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'d'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'b', 'b'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'d', 'd'})); + CHECK(!aut.is_in_lang(Word{'a', 'd'})); + CHECK(!aut.is_in_lang(Word{'a', 'd', 'c'})); + + CHECK(aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'a', 'e'})); + CHECK(aut.is_in_lang(Word{'d', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e', 'e'})); } SECTION("[abcd]*.*") { mata::parser::create_nfa(&aut, "[abcd]*.*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'d'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c'})); - - CHECK(is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'a', 'e'})); - CHECK(is_in_lang(aut, Word{'d', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e', 'e'})); - - CHECK(is_in_lang(aut, Word{'g'})); - CHECK(is_in_lang(aut, Word{'a', 'g'})); - CHECK(is_in_lang(aut, Word{'d', 'd', 'g'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'g'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'g'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'g', 'g'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'d'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c'})); + + CHECK(aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'a', 'e'})); + CHECK(aut.is_in_lang(Word{'d', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e', 'e'})); + + CHECK(aut.is_in_lang(Word{'g'})); + CHECK(aut.is_in_lang(Word{'a', 'g'})); + CHECK(aut.is_in_lang(Word{'d', 'd', 'g'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'g'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'g'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'g', 'g'})); } SECTION("[abcd]*.+") { mata::parser::create_nfa(&aut, "[abcd]*.+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'d'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c'})); - - CHECK(is_in_lang(aut, Word{'e'})); - CHECK(is_in_lang(aut, Word{'a', 'e'})); - CHECK(is_in_lang(aut, Word{'d', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'e', 'e'})); - - CHECK(is_in_lang(aut, Word{'g'})); - CHECK(is_in_lang(aut, Word{'a', 'g'})); - CHECK(is_in_lang(aut, Word{'d', 'd', 'g'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'g'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'g'})); - CHECK(is_in_lang(aut, Word{'a', 'd', 'c', 'g', 'g'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'d'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c'})); + + CHECK(aut.is_in_lang(Word{'e'})); + CHECK(aut.is_in_lang(Word{'a', 'e'})); + CHECK(aut.is_in_lang(Word{'d', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'e', 'e'})); + + CHECK(aut.is_in_lang(Word{'g'})); + CHECK(aut.is_in_lang(Word{'a', 'g'})); + CHECK(aut.is_in_lang(Word{'d', 'd', 'g'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'g'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'g'})); + CHECK(aut.is_in_lang(Word{'a', 'd', 'c', 'g', 'g'})); } SECTION("[a-c]+") { mata::parser::create_nfa(&aut, "[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'d'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'b', 'b'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'b'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'c'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'d'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'b', 'b'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'b'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'c'})); } SECTION("d[a-c]+") { mata::parser::create_nfa(&aut, "d[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'d'})); - CHECK(is_in_lang(aut, Word{'d', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'d', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'d', 'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'d', 'a', 'b'})); - CHECK(is_in_lang(aut, Word{'d', 'a', 'b', 'c'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'d'})); + CHECK(aut.is_in_lang(Word{'d', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'d', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'d', 'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'d', 'a', 'b'})); + CHECK(aut.is_in_lang(Word{'d', 'a', 'b', 'c'})); } SECTION("d*[a-c]+") { mata::parser::create_nfa(&aut, "d*[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'d'})); - CHECK(is_in_lang(aut, Word{'d', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'d', 'b', 'b'})); - CHECK(is_in_lang(aut, Word{'d', 'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'d', 'a', 'b'})); - CHECK(is_in_lang(aut, Word{'d', 'a', 'b', 'c'})); - CHECK(is_in_lang(aut, Word{'d', 'd', 'a', 'b', 'c'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'d'})); + CHECK(aut.is_in_lang(Word{'d', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'d', 'b', 'b'})); + CHECK(aut.is_in_lang(Word{'d', 'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'d', 'a', 'b'})); + CHECK(aut.is_in_lang(Word{'d', 'a', 'b', 'c'})); + CHECK(aut.is_in_lang(Word{'d', 'd', 'a', 'b', 'c'})); } SECTION("[^a-c]") { mata::parser::create_nfa(&aut, "[^a-c]"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'d'})); - CHECK(!is_in_lang(aut, Word{'d', 'd'})); - CHECK(is_in_lang(aut, Word{'e'})); - CHECK(!is_in_lang(aut, Word{'e', 'e'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'d'})); + CHECK(!aut.is_in_lang(Word{'d', 'd'})); + CHECK(aut.is_in_lang(Word{'e'})); + CHECK(!aut.is_in_lang(Word{'e', 'e'})); } SECTION("(ha)+") { mata::parser::create_nfa(&aut, "(ha)+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'h'})); - CHECK(is_in_lang(aut, Word{'h', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'h'})); - CHECK(is_in_lang(aut, Word{'h', 'a', 'h', 'a'})); - CHECK(!is_in_lang(aut, Word{'h', 'a', 'h'})); - CHECK(!is_in_lang(aut, Word{'h', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'h', 'a', 'h', 'a', 'h', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'h'})); + CHECK(aut.is_in_lang(Word{'h', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'h'})); + CHECK(aut.is_in_lang(Word{'h', 'a', 'h', 'a'})); + CHECK(!aut.is_in_lang(Word{'h', 'a', 'h'})); + CHECK(!aut.is_in_lang(Word{'h', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'h', 'a', 'h', 'a', 'h', 'a'})); } SECTION("(ha)*") { mata::parser::create_nfa(&aut, "(ha)*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'h'})); - CHECK(is_in_lang(aut, Word{'h', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'h'})); - CHECK(is_in_lang(aut, Word{'h', 'a', 'h', 'a'})); - CHECK(!is_in_lang(aut, Word{'h', 'a', 'h'})); - CHECK(!is_in_lang(aut, Word{'h', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'h', 'a', 'h', 'a', 'h', 'a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'h'})); + CHECK(aut.is_in_lang(Word{'h', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'h'})); + CHECK(aut.is_in_lang(Word{'h', 'a', 'h', 'a'})); + CHECK(!aut.is_in_lang(Word{'h', 'a', 'h'})); + CHECK(!aut.is_in_lang(Word{'h', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'h', 'a', 'h', 'a', 'h', 'a'})); } SECTION("b\\w{2,3}") { mata::parser::create_nfa(&aut, "b\\w{2,3}"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(!is_in_lang(aut, Word{'b', 'e'})); - CHECK(is_in_lang(aut, Word{'b', 'e', 'e'})); - CHECK(is_in_lang(aut, Word{'b', 'e', 'e', 'r'})); - CHECK(!is_in_lang(aut, Word{'b', 'e', 'e', 'r', 's'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(!aut.is_in_lang(Word{'b', 'e'})); + CHECK(aut.is_in_lang(Word{'b', 'e', 'e'})); + CHECK(aut.is_in_lang(Word{'b', 'e', 'e', 'r'})); + CHECK(!aut.is_in_lang(Word{'b', 'e', 'e', 'r', 's'})); } SECTION("b\\w+?") { mata::parser::create_nfa(&aut, "b\\w+?"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'b'})); - CHECK(is_in_lang(aut, Word{'b', 'e'})); - CHECK(!is_in_lang(aut, Word{'b', 'e', 'e'})); - CHECK(!is_in_lang(aut, Word{'b', 'e', 'e', 'r'})); - CHECK(!is_in_lang(aut, Word{'b', 'e', 'e', 'r', 's'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'b'})); + CHECK(aut.is_in_lang(Word{'b', 'e'})); + CHECK(!aut.is_in_lang(Word{'b', 'e', 'e'})); + CHECK(!aut.is_in_lang(Word{'b', 'e', 'e', 'r'})); + CHECK(!aut.is_in_lang(Word{'b', 'e', 'e', 'r', 's'})); } SECTION("b(a|e|i)d") { mata::parser::create_nfa(&aut, "b(a|e|i)d"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'b', 'a', 'd'})); - CHECK(!is_in_lang(aut, Word{'b', 'u', 'd'})); - CHECK(!is_in_lang(aut, Word{'b', 'o', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'e', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'i', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'b', 'a', 'd'})); + CHECK(!aut.is_in_lang(Word{'b', 'u', 'd'})); + CHECK(!aut.is_in_lang(Word{'b', 'o', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'e', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'i', 'd'})); } SECTION("[ab](c|d)") { mata::parser::create_nfa(&aut, "[ab](c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'd'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'e'})); - CHECK(!is_in_lang(aut, Word{'a', 'c', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'd'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'e'})); + CHECK(!aut.is_in_lang(Word{'a', 'c', 'd'})); } SECTION("[ab](c|d)") { mata::parser::create_nfa(&aut, "[ab](c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'd'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'e'})); - CHECK(!is_in_lang(aut, Word{'a', 'c', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'd'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'e'})); + CHECK(!aut.is_in_lang(Word{'a', 'c', 'd'})); } SECTION("[ab]+(c|d)") { mata::parser::create_nfa(&aut, "[ab]+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'a', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'e'})); - CHECK(!is_in_lang(aut, Word{'a', 'c', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'a', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'e'})); + CHECK(!aut.is_in_lang(Word{'a', 'c', 'd'})); } SECTION("([ab])+(c|d)") { mata::parser::create_nfa(&aut, "([ab])+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'a', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'e'})); - CHECK(!is_in_lang(aut, Word{'a', 'c', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'a', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'e'})); + CHECK(!aut.is_in_lang(Word{'a', 'c', 'd'})); } SECTION("(([ab])+)(c|d)") { mata::parser::create_nfa(&aut, "(([ab])+)(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'a', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'e'})); - CHECK(!is_in_lang(aut, Word{'a', 'c', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'a', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'e'})); + CHECK(!aut.is_in_lang(Word{'a', 'c', 'd'})); } SECTION("g|((([ab])+)(c|d))") { mata::parser::create_nfa(&aut, "(g|(([ab])+))(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'a', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'e'})); - CHECK(!is_in_lang(aut, Word{'a', 'c', 'd'})); - CHECK(is_in_lang(aut, Word{'g', 'c'})); - CHECK(is_in_lang(aut, Word{'g', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'a', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'e'})); + CHECK(!aut.is_in_lang(Word{'a', 'c', 'd'})); + CHECK(aut.is_in_lang(Word{'g', 'c'})); + CHECK(aut.is_in_lang(Word{'g', 'd'})); } SECTION("g|([ab])+(c|d)") { mata::parser::create_nfa(&aut, "g|([ab])+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'g'})); - CHECK(is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'd'})); - CHECK(is_in_lang(aut, Word{'b', 'd'})); - CHECK(is_in_lang(aut, Word{'a', 'a', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'b', 'a', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'e'})); - CHECK(!is_in_lang(aut, Word{'a', 'c', 'd'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'g'})); + CHECK(aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'd'})); + CHECK(aut.is_in_lang(Word{'b', 'd'})); + CHECK(aut.is_in_lang(Word{'a', 'a', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'b', 'a', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'e'})); + CHECK(!aut.is_in_lang(Word{'a', 'c', 'd'})); } SECTION("Star iteration") { @@ -977,102 +972,102 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(((c)*)((a)*))") { mata::parser::create_nfa(&aut, "(((c)*)((a)*))"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); CHECK(are_equivalent(aut, expected)); } SECTION("((c*)((a)*))") { mata::parser::create_nfa(&aut, "((c*)((a)*))"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); CHECK(are_equivalent(aut, expected)); } SECTION("(c*(a*))") { mata::parser::create_nfa(&aut, "(c*(a*))"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); CHECK(are_equivalent(aut, expected)); } SECTION("(c*a*)") { mata::parser::create_nfa(&aut, "(c*a*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); CHECK(are_equivalent(aut, expected)); } SECTION("c*a*") { mata::parser::create_nfa(&aut, "c*a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(is_in_lang(aut, Word{})); - CHECK(is_in_lang(aut, Word{'c'})); - CHECK(is_in_lang(aut, Word{'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c'})); - CHECK(is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(aut.is_in_lang(Word{})); + CHECK(aut.is_in_lang(Word{'c'})); + CHECK(aut.is_in_lang(Word{'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c'})); + CHECK(aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); CHECK(are_equivalent(aut, expected)); } SECTION("(((c)+)((a)+))") { mata::parser::create_nfa(&aut, "(((c)+)((a)+))"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); Nfa expected_plus_iteration{ 3 }; expected_plus_iteration.initial.insert(0); expected_plus_iteration.final.insert(2); @@ -1086,17 +1081,17 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("((c+)((a)+))") { mata::parser::create_nfa(&aut, "((c+)((a)+))"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); Nfa expected_plus_iteration{ 3 }; expected_plus_iteration.initial.insert(0); expected_plus_iteration.final.insert(2); @@ -1110,17 +1105,17 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("((c+)(a+))") { mata::parser::create_nfa(&aut, "((c+)(a+))"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); Nfa expected_plus_iteration{ 3 }; expected_plus_iteration.initial.insert(0); expected_plus_iteration.final.insert(2); @@ -1134,17 +1129,17 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(c+)(a+)") { mata::parser::create_nfa(&aut, "(c+)(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); Nfa expected_plus_iteration{ 3 }; expected_plus_iteration.initial.insert(0); expected_plus_iteration.final.insert(2); @@ -1158,17 +1153,17 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("c+(a+)") { mata::parser::create_nfa(&aut, "c+(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); Nfa expected_plus_iteration{ 3 }; expected_plus_iteration.initial.insert(0); expected_plus_iteration.final.insert(2); @@ -1182,17 +1177,17 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(c+)a+") { mata::parser::create_nfa(&aut, "(c+)a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); Nfa expected_plus_iteration{ 3 }; expected_plus_iteration.initial.insert(0); expected_plus_iteration.final.insert(2); @@ -1206,17 +1201,17 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("c+a+") { mata::parser::create_nfa(&aut, "c+a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.is_lang_empty()); - CHECK(!is_in_lang(aut, Word{})); - CHECK(!is_in_lang(aut, Word{'c'})); - CHECK(!is_in_lang(aut, Word{'a'})); - CHECK(!is_in_lang(aut, Word{'c', 'c'})); - CHECK(!is_in_lang(aut, Word{'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a'})); - CHECK(!is_in_lang(aut, Word{'a', 'c'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'a', 'a'})); - CHECK(is_in_lang(aut, Word{'c', 'c', 'a', 'a'})); + CHECK(!aut.empty_language()); + CHECK(!aut.is_in_lang(Word{})); + CHECK(!aut.is_in_lang(Word{'c'})); + CHECK(!aut.is_in_lang(Word{'a'})); + CHECK(!aut.is_in_lang(Word{'c', 'c'})); + CHECK(!aut.is_in_lang(Word{'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a'})); + CHECK(!aut.is_in_lang(Word{'a', 'c'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'a', 'a'})); + CHECK(aut.is_in_lang(Word{'c', 'c', 'a', 'a'})); Nfa expected_plus_iteration{ 3 }; expected_plus_iteration.initial.insert(0); expected_plus_iteration.final.insert(2); @@ -1236,9 +1231,9 @@ TEST_CASE("mata::Parser error") mata::nfa::Nfa aut; mata::parser::create_nfa(&aut, "((aa)*)*(b)*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.is_lang_empty()); - REQUIRE(is_in_lang(aut, Word{'a','a','b'})); - REQUIRE(!is_in_lang(aut, Word{'a','b'})); + REQUIRE(!aut.empty_language()); + REQUIRE(aut.is_in_lang(Word{'a','a','b'})); + REQUIRE(!aut.is_in_lang(Word{'a','b'})); } SECTION("Regexes from issue #48") @@ -1248,65 +1243,65 @@ TEST_CASE("mata::Parser error") mata::parser::create_nfa(&aut1, "[qQrR]*"); mata::parser::create_nfa(&aut2, "[qr]*"); REQUIRE(!aut1.delta.empty()); - REQUIRE(!aut1.is_lang_empty()); + REQUIRE(!aut1.empty_language()); REQUIRE(!aut2.delta.empty()); - REQUIRE(!aut2.is_lang_empty()); - REQUIRE(is_in_lang(aut1, Word{'Q','R','q','r'})); - REQUIRE(is_in_lang(aut2, Word{'q','r','q','r'})); - REQUIRE(!is_in_lang(aut2, Word{'q','R','q'})); + REQUIRE(!aut2.empty_language()); + REQUIRE(aut1.is_in_lang(Word{'Q','R','q','r'})); + REQUIRE(aut2.is_in_lang(Word{'q','r','q','r'})); + REQUIRE(!aut2.is_in_lang(Word{'q','R','q'})); } SECTION("Regex from issue #139") { Nfa x; mata::parser::create_nfa(&x, "(cd(abcde)*)|(a(aaa)*)"); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'a', 'a' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'd' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'a', 'a' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'd' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); x.clear(); mata::parser::create_nfa(&x, "(cd(abcde)*)|(a(aaa)*)", false, 306, false); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'a', 'a' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'd' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'a', 'a' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'd' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); } SECTION("Another failing regex") { Nfa x; mata::parser::create_nfa(&x, "(cd(abcde)+)|(a(aaa)+|ccc+)"); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'a', 'a' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'c', 'c' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'c', 'd' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'c', 'c' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'c', 'c', 'c', 'c', 'c' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'a', 'a' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'c', 'c' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'c', 'd' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'c', 'c' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'c', 'c', 'c', 'c', 'c' }, {} })); x.clear(); mata::parser::create_nfa(&x, "(cd(abcde)+)|(a(aaa)+|ccc+)", false, 306, false); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'a', 'a' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'c', 'c' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'c', 'd' }, {} })); - CHECK(!is_in_lang(x, Run{ Word{ 'c', 'c' }, {} })); - CHECK(is_in_lang(x, Run{ Word{ 'c', 'c', 'c', 'c', 'c', 'c' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'a', 'a' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'a', 'a', 'a', 'a', 'a', 'a', 'a' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'c', 'd', 'a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'e' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'c', 'c' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'c', 'd' }, {} })); + CHECK(!x.is_in_lang(Run{ Word{ 'c', 'c' }, {} })); + CHECK(x.is_in_lang(Run{ Word{ 'c', 'c', 'c', 'c', 'c', 'c' }, {} })); } } // }}} @@ -1316,6 +1311,6 @@ TEST_CASE("mata::Parser bug epsilon") { Nfa x; mata::parser::create_nfa(&x, "(cd(abcde)*)|(a(aaa)*)"); - CHECK(is_in_lang(x, Run{Word{'a', 'a', 'a', 'a'}, {}})); + CHECK(x.is_in_lang(Run{Word{'a', 'a', 'a', 'a'}, {}})); } } // }}} diff --git a/tests/strings/nfa-string-solving.cc b/tests/strings/nfa-string-solving.cc index 0de3ff4c2..385af77a9 100644 --- a/tests/strings/nfa-string-solving.cc +++ b/tests/strings/nfa-string-solving.cc @@ -288,7 +288,7 @@ TEST_CASE("mata::nfa::create_single_word_nfa()") { SECTION("Simple word") { std::vector word{ 10, 20, 30, 40, 50, 60 }; auto nfa{ builder::create_single_word_nfa(word) }; - CHECK(is_in_lang(nfa, { word, {} })); + CHECK(nfa.is_in_lang(word)); CHECK(nfa.final.size() == 1); CHECK(nfa.initial.size() == 1); CHECK(mata::strings::get_word_lengths(nfa) == std::set>{ std::make_pair(6, 0) }); @@ -297,7 +297,7 @@ TEST_CASE("mata::nfa::create_single_word_nfa()") { SECTION("Empty string") { std::vector word{}; auto nfa{ builder::create_single_word_nfa(word) }; - CHECK(is_in_lang(nfa, { word, {} })); + CHECK(nfa.is_in_lang(word)); CHECK(mata::strings::is_lang_eps(nfa)); CHECK(nfa.final.size() == 1); CHECK(nfa.initial.size() == 1); @@ -309,7 +309,7 @@ TEST_CASE("mata::nfa::create_single_word_nfa()") { SECTION("Simple word") { std::vector word{ "zero", "one", "two", "three", "four", "five" }; auto nfa{ builder::create_single_word_nfa(word) }; - CHECK(is_in_lang(nfa, { nfa.alphabet->translate_word(word), {} })); + CHECK(nfa.is_in_lang(nfa.alphabet->translate_word(word))); CHECK(nfa.final.size() == 1); CHECK(nfa.initial.size() == 1); CHECK(mata::strings::get_word_lengths(nfa) == std::set>{ std::make_pair(6, 0) }); @@ -318,7 +318,7 @@ TEST_CASE("mata::nfa::create_single_word_nfa()") { SECTION("Empty string") { std::vector word{}; auto nfa{ builder::create_single_word_nfa(word) }; - CHECK(is_in_lang(nfa, { word, {} })); + CHECK(nfa.is_in_lang(word)); CHECK(mata::strings::is_lang_eps(nfa)); CHECK(nfa.final.size() == 1); CHECK(nfa.initial.size() == 1); @@ -332,7 +332,7 @@ TEST_CASE("mata::nfa::create_single_word_nfa()") { alphabet.add_new_symbol(word[symbol], symbol); } auto nfa{ builder::create_single_word_nfa(word) }; - CHECK(is_in_lang(nfa, { nfa.alphabet->translate_word(word), {} })); + CHECK(nfa.is_in_lang(nfa.alphabet->translate_word(word))); CHECK(nfa.final.size() == 1); CHECK(nfa.initial.size() == 1); CHECK(mata::strings::get_word_lengths(nfa) == std::set>{ std::make_pair(6, 0) }); From 1f9c3739f64f33880a222d1e345a1acafa4d3271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 11 Sep 2023 12:09:10 +0200 Subject: [PATCH 20/23] Move 'get_word_for_path()' to 'Nfa' --- bindings/python/libmata/nfa/nfa.pxd | 2 +- bindings/python/libmata/nfa/nfa.pyx | 31 +++--- bindings/python/tests/test_nfa.py | 14 +-- include/mata/nfa/nfa.hh | 3 +- src/nfa/operations.cc | 28 ++---- tests/nfa/nfa.cc | 14 +-- tests/re2parser.cc | 144 ++++++++++++++-------------- 7 files changed, 108 insertions(+), 128 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 273c6b51e..692174a9c 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -174,6 +174,7 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": bool is_universal(CAlphabet&, ParameterMap&) except + bool is_in_lang(CRun&) bool is_prfx_in_lang(CRun&) + pair[CRun, bool] get_word_for_path(CRun&) # Automata tests cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) @@ -185,7 +186,6 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": cdef void compute_fw_direct_simulation(const CNfa&) # Helper functions - cdef pair[CRun, bool] c_get_word_for_path "mata::nfa::get_word_for_path" (CNfa&, CRun&) cdef CRun c_encode_word "mata::nfa::encode_word" (CAlphabet*, vector[string]) cdef extern from "mata/nfa/algorithms.hh" namespace "mata::nfa::algorithms": diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index b9c5b6e65..92f108a82 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -746,6 +746,21 @@ cdef class Nfa: run.thisptr.word = word return self.thisptr.get().is_prfx_in_lang(dereference(run.thisptr)) + def get_word_for_path(self, path): + """For a given path (set of states) returns a corresponding word + + >>> lhs.get_word_for_path([0, 1, 2]) + ([1, 1], True) + + :param Nfa lhs: source automaton + :param list path: list of states + :return: pair of word (list of symbols) and true or false, whether the search was successful + """ + input = Run() + input.path = path + cdef pair[CRun, bool] result = self.thisptr.get().get_word_for_path(dereference(input.thisptr)) + return result.first.word, result.second + def get_symbols(self): """Return a set of symbols used on the transitions in NFA. @@ -1098,22 +1113,6 @@ def accepts_epsilon(Nfa lhs): return False # Helper functions -def get_word_for_path(Nfa lhs, path): - """For a given path (set of states) returns a corresponding word - - >>> mata_nfa.Nfa.get_word_for_path(lhs, [0, 1, 2]) - ([1, 1], True) - - :param Nfa lhs: source automaton - :param list path: list of states - :return: pair of word (list of symbols) and true or false, whether the search was successful - """ - cdef pair[CRun, bool] result - input = Run() - input.path = path - result = mata_nfa.c_get_word_for_path(dereference(lhs.thisptr.get()), dereference(input.thisptr)) - return result.first.word, result.second - def encode_word(alph.Alphabet alphabet, word): """Encodes word based on a passed alphabet diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index 43df04571..47531dfe6 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -207,15 +207,11 @@ def test_forward_reach_states( def test_get_word_for_path( fa_one_divisible_by_two, fa_one_divisible_by_four, fa_one_divisible_by_eight ): - assert mata_nfa.get_word_for_path(fa_one_divisible_by_two, [0, 1, 2]) == ([1, 1], True) - assert mata_nfa.get_word_for_path(fa_one_divisible_by_two, [0, 1, 2, 0]) == ([], False) - assert mata_nfa.get_word_for_path(fa_one_divisible_by_two, [0, 1, 2, 2]) == ([1, 1, 0], True) - assert mata_nfa.get_word_for_path( - fa_one_divisible_by_four, [0, 1, 2, 3, 4] - ) == ([1, 1, 1, 1], True) - assert mata_nfa.get_word_for_path( - fa_one_divisible_by_eight, [0, 1, 2, 3, 4, 5, 6, 7, 8] - ) == ([1, 1, 1, 1, 1, 1, 1, 1], True) + assert fa_one_divisible_by_two.get_word_for_path([0, 1, 2]) == ([1, 1], True) + assert fa_one_divisible_by_two.get_word_for_path([0, 1, 2, 0]) == ([], False) + assert fa_one_divisible_by_two.get_word_for_path([0, 1, 2, 2]) == ([1, 1, 0], True) + assert fa_one_divisible_by_four.get_word_for_path([0, 1, 2, 3, 4]) == ([1, 1, 1, 1], True) + assert fa_one_divisible_by_eight.get_word_for_path([0, 1, 2, 3, 4, 5, 6, 7, 8]) == ([1, 1, 1, 1, 1, 1, 1, 1], True) def test_encode_word(): diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index ca1cf2e60..b41fe8927 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -301,6 +301,7 @@ public: /// Checks whether the prefix of a string is in the language of an automaton bool is_prfx_in_lang(const Run& word) const; + std::pair get_word_for_path(const Run& run) const; }; // struct Nfa. // Allow variadic number of arguments of the same type. @@ -587,8 +588,6 @@ Nfa somewhat_simple_revert(const Nfa& aut); // Removing epsilon transitions Nfa remove_epsilon(const Nfa& aut, Symbol epsilon = EPSILON); -std::pair get_word_for_path(const Nfa& aut, const Run& run); - /** Encodes a vector of strings (each corresponding to one symbol) into a * @c Word instance */ diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 1809297cb..2db56d588 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -467,23 +467,16 @@ bool mata::nfa::Nfa::is_complete(Alphabet const* alphabet) const { return true; } -std::pair mata::nfa::get_word_for_path(const Nfa& aut, const Run& run) -{ - if (run.path.empty()) - { - return {{}, true}; - } +std::pair mata::nfa::Nfa::get_word_for_path(const Run& run) const { + if (run.path.empty()) { return {{}, true}; } Run word; State cur = run.path[0]; - for (size_t i = 1; i < run.path.size(); ++i) - { + for (size_t i = 1; i < run.path.size(); ++i) { State newSt = run.path[i]; bool found = false; - - if (!aut.delta.empty()) - { - for (const auto &symbolMap: aut.delta[cur]) { + if (!this->delta.empty()) { + for (const auto &symbolMap: this->delta[cur]) { for (State st: symbolMap.targets) { if (st == newSt) { word.word.push_back(symbolMap.symbol); @@ -491,19 +484,12 @@ std::pair mata::nfa::get_word_for_path(const Nfa& aut, const Run& run break; } } - if (found) { break; } } } - - if (!found) - { - return {{}, false}; - } - + if (!found) { return {{}, false}; } cur = newSt; // update current state } - return {word, true}; } @@ -553,7 +539,7 @@ bool mata::nfa::Nfa::is_lang_empty(Run* cex) const { cex->path.push_back(state); } std::reverse(cex->path.begin(), cex->path.end()); - cex->word = get_word_for_path(*this, *cex).first.word; + cex->word = this->get_word_for_path(*cex).first.word; } return false; } diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 2be5e43a7..0ee4d0908 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -273,7 +273,7 @@ TEST_CASE("mata::nfa::get_word_for_path()") { path = { }; - auto word_bool_pair = get_word_for_path(aut, path); + auto word_bool_pair = aut.get_word_for_path(path); REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word.empty()); } @@ -283,7 +283,7 @@ TEST_CASE("mata::nfa::get_word_for_path()") aut.initial = {1}; path.path = {1}; - auto word_bool_pair = get_word_for_path(aut, path); + auto word_bool_pair = aut.get_word_for_path(path); REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word.empty()); } @@ -298,7 +298,7 @@ TEST_CASE("mata::nfa::get_word_for_path()") path.path = {1,2,3}; - auto word_bool_pair = get_word_for_path(aut, path); + auto word_bool_pair = aut.get_word_for_path(path); REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word == Word({'c', 'b'})); } @@ -315,7 +315,7 @@ TEST_CASE("mata::nfa::get_word_for_path()") path.path = {1,2,3,2,4}; - auto word_bool_pair = get_word_for_path(aut, path); + auto word_bool_pair = aut.get_word_for_path(path); std::set possible({ Word({'c', 'b', 'd', 'a'}), Word({'a', 'b', 'd', 'a'})}); @@ -335,7 +335,7 @@ TEST_CASE("mata::nfa::get_word_for_path()") path.path = {1,2,3,1,2}; - auto word_bool_pair = get_word_for_path(aut, path); + auto word_bool_pair = aut.get_word_for_path(path); REQUIRE(!word_bool_pair.second); } } @@ -516,7 +516,7 @@ TEST_CASE("mata::nfa::construct() correct calls") Run cex; REQUIRE(!aut.is_lang_empty(&cex)); - auto word_bool_pair = get_word_for_path(aut, cex); + auto word_bool_pair = aut.get_word_for_path(cex); REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word == encode_word(&alphabet, { "a"}).word); @@ -687,7 +687,7 @@ TEST_CASE("mata::nfa::construct() from IntermediateAut correct calls") Run cex; REQUIRE(!aut.is_lang_empty(&cex)); - auto word_bool_pair = get_word_for_path(aut, cex); + auto word_bool_pair = aut.get_word_for_path(cex); REQUIRE(word_bool_pair.second); REQUIRE(word_bool_pair.first.word == encode_word(&alphabet, { "a" }).word); diff --git a/tests/re2parser.cc b/tests/re2parser.cc index cd819e9fa..52db3740f 100644 --- a/tests/re2parser.cc +++ b/tests/re2parser.cc @@ -25,7 +25,7 @@ TEST_CASE("mata::Parser basic_parsing") { { mata::parser::create_nfa(&aut, "abcd"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.empty_language()); + REQUIRE(!aut.is_lang_empty()); REQUIRE(!aut.is_in_lang(Word{'a','b','c'})); REQUIRE(aut.is_in_lang(Word{'a','b','c','d'})); REQUIRE(!aut.is_in_lang(Word{'a','b','c','d','d'})); @@ -36,7 +36,7 @@ TEST_CASE("mata::Parser basic_parsing") { { mata::parser::create_nfa(&aut, "\\x7f"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.empty_language()); + REQUIRE(!aut.is_lang_empty()); REQUIRE(aut.is_in_lang(Word{127})); } @@ -44,7 +44,7 @@ TEST_CASE("mata::Parser basic_parsing") { { mata::parser::create_nfa(&aut, ".*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.empty_language()); + REQUIRE(!aut.is_lang_empty()); REQUIRE(aut.is_in_lang(Word{'w','h','a','t','e','v','e','r'})); REQUIRE(aut.is_in_lang(Word{127})); REQUIRE(aut.is_in_lang(Word{0x7f})); @@ -56,7 +56,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Special character") { mata::parser::create_nfa(&aut, "\\t"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{'\t'})); CHECK(!aut.is_in_lang(Word{'t'})); CHECK(!aut.is_in_lang(Word{})); @@ -65,7 +65,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Whitespace") { mata::parser::create_nfa(&aut, "a\\sb"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{'a', '\t', 'b'})); CHECK(!aut.is_in_lang(Word{})); } @@ -74,7 +74,7 @@ TEST_CASE("mata::Parser basic_parsing") { { mata::parser::create_nfa(&aut, "ab*cd*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.empty_language()); + REQUIRE(!aut.is_lang_empty()); REQUIRE(aut.is_in_lang(Word{'a','b','c'})); REQUIRE(aut.is_in_lang(Word{'a','b','c','d'})); REQUIRE(aut.is_in_lang(Word{'a','c','d'})); @@ -135,7 +135,7 @@ TEST_CASE("mata::Parser basic_parsing") { } CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{'b'})); CHECK(aut.is_in_lang(Word{'a','b'})); CHECK(aut.is_in_lang(Word{'a','a','b'})); @@ -146,7 +146,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Complex regex") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -164,7 +164,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Complex regex with additional plus") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -181,7 +181,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Reduced complex regex with additional plus") { mata::parser::create_nfa(&aut, "(e)(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -198,7 +198,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Reduced complex regex with additional plus 2") { mata::parser::create_nfa(&aut, "(w*)+(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -216,7 +216,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Reduced complex regex with additional plus 2.5") { mata::parser::create_nfa(&aut, "(w*)(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -234,7 +234,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Reduced complex regex with additional plus 2.63") { mata::parser::create_nfa(&aut, "w*b+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -252,7 +252,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Reduced complex regex with additional plus 2.75") { mata::parser::create_nfa(&aut, "w(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -270,7 +270,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Reduced complex regex with additional plus 2.85") { mata::parser::create_nfa(&aut, "w*(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -288,7 +288,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Reduced complex regex with additional plus 3") { mata::parser::create_nfa(&aut, "(b+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -301,7 +301,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Complex regex 2") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)(b*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -320,7 +320,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("Complex regex 2 with additional plus") { mata::parser::create_nfa(&aut, "(a+)|(e)(w*)+(b*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -339,7 +339,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("a+b+") { mata::parser::create_nfa(&aut, "a+b+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -353,7 +353,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("a+b+a*") { mata::parser::create_nfa(&aut, "a+b+a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -369,7 +369,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("a+(b+)a*") { mata::parser::create_nfa(&aut, "a+(b+)a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -385,7 +385,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(a+(b+)a*)") { mata::parser::create_nfa(&aut, "(a+(b+)a*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'a', 'a'})); @@ -401,7 +401,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(a+b*a*)") { mata::parser::create_nfa(&aut, "(a+b*a*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -417,7 +417,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("a+a+") { mata::parser::create_nfa(&aut, "a+a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -428,7 +428,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(a+)a+") { mata::parser::create_nfa(&aut, "(a+)a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -439,7 +439,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("a(a+)") { mata::parser::create_nfa(&aut, "a(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'a'})); @@ -450,7 +450,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(a+)b") { mata::parser::create_nfa(&aut, "(a+)b"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'a', 'b'})); @@ -461,7 +461,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b(a+)") { mata::parser::create_nfa(&aut, "b(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b', 'a'})); @@ -472,7 +472,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b|(a+)") { mata::parser::create_nfa(&aut, "b|(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -485,7 +485,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b|a+") { mata::parser::create_nfa(&aut, "b|a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -498,7 +498,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b|a") { mata::parser::create_nfa(&aut, "b|a"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -511,7 +511,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b|a*") { mata::parser::create_nfa(&aut, "b|a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -524,7 +524,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("bba+") { mata::parser::create_nfa(&aut, "bba+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'b'})); @@ -538,7 +538,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b*ba+") { mata::parser::create_nfa(&aut, "b*ba+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'b'})); @@ -554,7 +554,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b*ca+") { mata::parser::create_nfa(&aut, "b*ca+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'b'})); @@ -571,7 +571,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[abcd]") { mata::parser::create_nfa(&aut, "[abcd]"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -583,7 +583,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[abcd]*") { mata::parser::create_nfa(&aut, "[abcd]*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -600,7 +600,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[abcd]*e*") { mata::parser::create_nfa(&aut, "[abcd]*e*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -623,7 +623,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[abcd]*e+") { mata::parser::create_nfa(&aut, "[abcd]*e+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'b'})); @@ -647,7 +647,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[abcd]*.*") { mata::parser::create_nfa(&aut, "[abcd]*.*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -678,7 +678,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[abcd]*.+") { mata::parser::create_nfa(&aut, "[abcd]*.+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -709,7 +709,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[a-c]+") { mata::parser::create_nfa(&aut, "[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -726,7 +726,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("d[a-c]+") { mata::parser::create_nfa(&aut, "d[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'b'})); @@ -743,7 +743,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("d*[a-c]+") { mata::parser::create_nfa(&aut, "d*[a-c]+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a'})); CHECK(aut.is_in_lang(Word{'b'})); @@ -761,7 +761,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[^a-c]") { mata::parser::create_nfa(&aut, "[^a-c]"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'b'})); @@ -775,7 +775,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(ha)+") { mata::parser::create_nfa(&aut, "(ha)+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'h'})); @@ -790,7 +790,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(ha)*") { mata::parser::create_nfa(&aut, "(ha)*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'a'})); CHECK(!aut.is_in_lang(Word{'h'})); @@ -805,7 +805,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b\\w{2,3}") { mata::parser::create_nfa(&aut, "b\\w{2,3}"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'b'})); CHECK(!aut.is_in_lang(Word{'b', 'e'})); @@ -817,7 +817,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b\\w+?") { mata::parser::create_nfa(&aut, "b\\w+?"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'b'})); CHECK(aut.is_in_lang(Word{'b', 'e'})); @@ -829,7 +829,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("b(a|e|i)d") { mata::parser::create_nfa(&aut, "b(a|e|i)d"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'b', 'a', 'd'})); CHECK(!aut.is_in_lang(Word{'b', 'u', 'd'})); @@ -841,7 +841,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[ab](c|d)") { mata::parser::create_nfa(&aut, "[ab](c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a', 'c'})); CHECK(aut.is_in_lang(Word{'b', 'c'})); @@ -856,7 +856,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[ab](c|d)") { mata::parser::create_nfa(&aut, "[ab](c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a', 'c'})); CHECK(aut.is_in_lang(Word{'b', 'c'})); @@ -871,7 +871,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("[ab]+(c|d)") { mata::parser::create_nfa(&aut, "[ab]+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a', 'c'})); CHECK(aut.is_in_lang(Word{'b', 'c'})); @@ -889,7 +889,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("([ab])+(c|d)") { mata::parser::create_nfa(&aut, "([ab])+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a', 'c'})); CHECK(aut.is_in_lang(Word{'b', 'c'})); @@ -907,7 +907,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(([ab])+)(c|d)") { mata::parser::create_nfa(&aut, "(([ab])+)(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a', 'c'})); CHECK(aut.is_in_lang(Word{'b', 'c'})); @@ -925,7 +925,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("g|((([ab])+)(c|d))") { mata::parser::create_nfa(&aut, "(g|(([ab])+))(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'a', 'c'})); CHECK(aut.is_in_lang(Word{'b', 'c'})); @@ -945,7 +945,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("g|([ab])+(c|d)") { mata::parser::create_nfa(&aut, "g|([ab])+(c|d)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'g'})); CHECK(aut.is_in_lang(Word{'a', 'c'})); @@ -972,7 +972,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(((c)*)((a)*))") { mata::parser::create_nfa(&aut, "(((c)*)((a)*))"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'c'})); CHECK(aut.is_in_lang(Word{'a'})); @@ -989,7 +989,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("((c*)((a)*))") { mata::parser::create_nfa(&aut, "((c*)((a)*))"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'c'})); CHECK(aut.is_in_lang(Word{'a'})); @@ -1006,7 +1006,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(c*(a*))") { mata::parser::create_nfa(&aut, "(c*(a*))"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'c'})); CHECK(aut.is_in_lang(Word{'a'})); @@ -1023,7 +1023,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(c*a*)") { mata::parser::create_nfa(&aut, "(c*a*)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'c'})); CHECK(aut.is_in_lang(Word{'a'})); @@ -1040,7 +1040,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("c*a*") { mata::parser::create_nfa(&aut, "c*a*"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(aut.is_in_lang(Word{})); CHECK(aut.is_in_lang(Word{'c'})); CHECK(aut.is_in_lang(Word{'a'})); @@ -1057,7 +1057,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(((c)+)((a)+))") { mata::parser::create_nfa(&aut, "(((c)+)((a)+))"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'c'})); CHECK(!aut.is_in_lang(Word{'a'})); @@ -1081,7 +1081,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("((c+)((a)+))") { mata::parser::create_nfa(&aut, "((c+)((a)+))"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'c'})); CHECK(!aut.is_in_lang(Word{'a'})); @@ -1105,7 +1105,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("((c+)(a+))") { mata::parser::create_nfa(&aut, "((c+)(a+))"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'c'})); CHECK(!aut.is_in_lang(Word{'a'})); @@ -1129,7 +1129,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(c+)(a+)") { mata::parser::create_nfa(&aut, "(c+)(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'c'})); CHECK(!aut.is_in_lang(Word{'a'})); @@ -1153,7 +1153,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("c+(a+)") { mata::parser::create_nfa(&aut, "c+(a+)"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'c'})); CHECK(!aut.is_in_lang(Word{'a'})); @@ -1177,7 +1177,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("(c+)a+") { mata::parser::create_nfa(&aut, "(c+)a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'c'})); CHECK(!aut.is_in_lang(Word{'a'})); @@ -1201,7 +1201,7 @@ TEST_CASE("mata::Parser basic_parsing") { SECTION("c+a+") { mata::parser::create_nfa(&aut, "c+a+"); CHECK(!aut.delta.empty()); - CHECK(!aut.empty_language()); + CHECK(!aut.is_lang_empty()); CHECK(!aut.is_in_lang(Word{})); CHECK(!aut.is_in_lang(Word{'c'})); CHECK(!aut.is_in_lang(Word{'a'})); @@ -1231,7 +1231,7 @@ TEST_CASE("mata::Parser error") mata::nfa::Nfa aut; mata::parser::create_nfa(&aut, "((aa)*)*(b)*"); REQUIRE(!aut.delta.empty()); - REQUIRE(!aut.empty_language()); + REQUIRE(!aut.is_lang_empty()); REQUIRE(aut.is_in_lang(Word{'a','a','b'})); REQUIRE(!aut.is_in_lang(Word{'a','b'})); } @@ -1243,9 +1243,9 @@ TEST_CASE("mata::Parser error") mata::parser::create_nfa(&aut1, "[qQrR]*"); mata::parser::create_nfa(&aut2, "[qr]*"); REQUIRE(!aut1.delta.empty()); - REQUIRE(!aut1.empty_language()); + REQUIRE(!aut1.is_lang_empty()); REQUIRE(!aut2.delta.empty()); - REQUIRE(!aut2.empty_language()); + REQUIRE(!aut2.is_lang_empty()); REQUIRE(aut1.is_in_lang(Word{'Q','R','q','r'})); REQUIRE(aut2.is_in_lang(Word{'q','r','q','r'})); REQUIRE(!aut2.is_in_lang(Word{'q','R','q'})); From d5ff89b1f6282dc60dae8136fbf652b67c734bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 11 Sep 2023 13:02:16 +0200 Subject: [PATCH 21/23] Move 'make_complete()' to 'Nfa' --- bindings/python/libmata/nfa/nfa.pxd | 2 +- bindings/python/libmata/nfa/nfa.pyx | 21 ++++--- bindings/python/tests/test_nfa.py | 2 +- include/mata/nfa/nfa.hh | 90 ++++++++++++++--------------- include/mata/nfa/plumbing.hh | 3 - src/nfa/complement.cc | 2 +- src/nfa/operations.cc | 14 ++--- tests/nfa/nfa-plumbing.cc | 5 -- tests/nfa/nfa.cc | 14 ++--- 9 files changed, 72 insertions(+), 81 deletions(-) diff --git a/bindings/python/libmata/nfa/nfa.pxd b/bindings/python/libmata/nfa/nfa.pxd index 692174a9c..674829971 100644 --- a/bindings/python/libmata/nfa/nfa.pxd +++ b/bindings/python/libmata/nfa/nfa.pxd @@ -175,6 +175,7 @@ cdef extern from "mata/nfa/nfa.hh" namespace "mata::nfa": bool is_in_lang(CRun&) bool is_prfx_in_lang(CRun&) pair[CRun, bool] get_word_for_path(CRun&) + void make_complete(CAlphabet&, State) except + # Automata tests cdef bool c_is_included "mata::nfa::is_included" (CNfa&, CNfa&, CAlphabet*, ParameterMap&) @@ -198,7 +199,6 @@ cdef extern from "mata/nfa/plumbing.hh" namespace "mata::nfa::plumbing": cdef void c_intersection "mata::nfa::plumbing::intersection" (CNfa*, CNfa&, CNfa&, bool, umap[pair[State, State], State]*) cdef void c_concatenate "mata::nfa::plumbing::concatenate" (CNfa*, CNfa&, CNfa&, bool, StateRenaming*, StateRenaming*) cdef void c_complement "mata::nfa::plumbing::complement" (CNfa*, CNfa&, CAlphabet&, ParameterMap&) except + - cdef void c_make_complete "mata::nfa::plumbing::make_complete" (CNfa*, CAlphabet&, State) except + cdef void c_revert "mata::nfa::plumbing::revert" (CNfa*, CNfa&) cdef void c_remove_epsilon "mata::nfa::plumbing::remove_epsilon" (CNfa*, CNfa&, Symbol) except + cdef void c_minimize "mata::nfa::plumbing::minimize" (CNfa*, CNfa&) diff --git a/bindings/python/libmata/nfa/nfa.pyx b/bindings/python/libmata/nfa/nfa.pyx index 92f108a82..941e2fc89 100644 --- a/bindings/python/libmata/nfa/nfa.pyx +++ b/bindings/python/libmata/nfa/nfa.pyx @@ -761,6 +761,16 @@ cdef class Nfa: cdef pair[CRun, bool] result = self.thisptr.get().get_word_for_path(dereference(input.thisptr)) return result.first.word, result.second + def make_complete(self, State sink_state, alph.Alphabet alphabet): + """Makes NFA complete. + + :param Symbol sink_state: sink state of the automaton + :param OnTheFlyAlphabet alphabet: alphabet to make complete against. + """ + if not self.thisptr.get().is_state(sink_state): + self.thisptr.get().add_state(self.thisptr.get().num_of_states()) + self.thisptr.get().make_complete(dereference(alphabet.as_base()), sink_state) + def get_symbols(self): """Return a set of symbols used on the transitions in NFA. @@ -914,17 +924,6 @@ def complement(Nfa lhs, alph.Alphabet alphabet, params = None): ) return result -def make_complete(Nfa lhs, State sink_state, alph.Alphabet alphabet): - """Makes lhs complete - - :param Nfa lhs: automaton that will be made complete - :param Symbol sink_state: sink state of the automaton - :param OnTheFlyAlphabet alphabet: alphabet of the - """ - if not lhs.thisptr.get().is_state(sink_state): - lhs.thisptr.get().add_state(lhs.num_of_states()) - mata_nfa.c_make_complete(lhs.thisptr.get(), dereference(alphabet.as_base()), sink_state) - def revert(Nfa lhs): """Reverses transitions in the lhs diff --git a/bindings/python/tests/test_nfa.py b/bindings/python/tests/test_nfa.py index 47531dfe6..b7b237ea6 100644 --- a/bindings/python/tests/test_nfa.py +++ b/bindings/python/tests/test_nfa.py @@ -377,7 +377,7 @@ def test_completeness( r.make_initial_state(0) r.add_transition(0, 0, 0) assert not r.is_complete(alph) - mata_nfa.make_complete(r, 1, alph) + r.make_complete(1, alph) assert r.is_complete(alph) diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index b41fe8927..494bb7b8d 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -302,6 +302,51 @@ public: bool is_prfx_in_lang(const Run& word) const; std::pair get_word_for_path(const Run& run) const; + + /** + * @brief Make NFA complete in place. + * + * For each state 0,...,this->num_of_states()-1, add transitions with "missing" symbols from @p alphabet + * (symbols that do not occur on transitions from given state) to @p sink_state. If @p sink_state does not belong + * to the NFA, it is added to it, but only in the case that some transition to @p sink_state was added. + * In the case that NFA does not contain any states, this function does nothing. + * + * @param[in] alphabet Alphabet to use for computing "missing" symbols. + * @param[in] sink_state The state into which new transitions are added. + * @return True if some new transition was added to the NFA. + */ + bool make_complete(const Alphabet& alphabet, State sink_state); + + /** + * @brief Make NFA complete in place. + * + * For each state 0,...,this->num_of_states()-1, add transitions with "missing" symbols from @p alphabet + * (symbols that do not occur on transitions from given state) to @p sink_state. If @p sink_state does not belong + * to the NFA, it is added to it, but only in the case that some transition to @p sink_state was added. + * In the case that NFA does not contain any states, this function does nothing. + * + * This overloaded version is a more efficient version which does not need to compute the set of symbols to + * complete to from the alphabet. Prefer this version when you already have the set of symbols precomputed or plan + * to complete multiple automata over the same set of symbols. + * + * @param[in] symbols Symbols to compute missing symbols from. + * @param[in] sink_state The state into which new transitions are added. + * @return True if some new transition was added to the automaton. + */ + bool make_complete(const utils::OrdVector& symbols, State sink_state); + + /** + * @brief Make NFA complete in place. + * + * For each state 0,...,this->num_of_states()-1, add transitions with "missing" symbols from @p alphabet + * (symbols that do not occur on transitions from given state) to new sink state (if no new transitions are added, + * this sink state is not created). + * In the case that NFA does not contain any states, this function does nothing. + * + * @param[in] alphabet Alphabet to use for computing "missing" symbols. + * @return True if some new transition (and sink state) was added to the automaton. + */ + bool make_complete(const Alphabet& alphabet) { return this->make_complete(alphabet, this->num_of_states()); } }; // struct Nfa. // Allow variadic number of arguments of the same type. @@ -397,51 +442,6 @@ Nfa intersection(const Nfa& lhs, const Nfa& rhs, Nfa concatenate(const Nfa& lhs, const Nfa& rhs, bool use_epsilon = false, StateRenaming* lhs_state_renaming = nullptr, StateRenaming* rhs_state_renaming = nullptr); -/** - * Make @c aut complete in place. - * - * For each state 0,...,aut.num_of_states()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur - * on transitions from given state) to @p sink_state. If @p sink_state does not belong to the automaton, it is added to - * it, but only in the case that some transition to @p sink_state was added. - * In the case that @p aut does not contain any states, this function does nothing. - * - * @param[in] aut Automaton to make complete. - * @param[in] alphabet Alphabet to use for computing "missing" symbols. - * @param[in] sink_state The state into which new transitions are added. - * @return True if some new transition was added to the automaton. - */ -bool make_complete(Nfa& aut, const Alphabet& alphabet, State sink_state); - -/** - * Make @c aut complete in place. - * - * For each state 0,...,aut.num_of_states()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur - * on transitions from given state) to @p sink_state. If @p sink_state does not belong to the automaton, it is added to - * it, but only in the case that some transition to @p sink_state was added. - * In the case that @p aut does not contain any states, this function does nothing. - * - * This overloaded version is a more efficient version which does not need to compute the set of symbols to complete to - * from the alphabet. Prefer this version when you already have the set of symbols precomputed or plan to complete - * multiple automata over the same set of symbols. - * - * @param[in] aut Automaton to make complete. - * @param[in] symbols Symbols to compute missing symbols from. - * @param[in] sink_state The state into which new transitions are added. - * @return True if some new transition was added to the automaton. - */ -bool make_complete(Nfa& aut, const utils::OrdVector& symbols, State sink_state); - -/** - * For each state 0,...,aut.num_of_states()-1, add transitions with "missing" symbols from @p alphabet (symbols that do not occur - * on transitions from given state) to new sink state (if no new transitions are added, this sink state is not created). - * In the case that @p aut does not contain any states, this function does nothing. - * - * @param[in] aut Automaton to make complete. - * @param[in] alphabet Alphabet to use for computing "missing" symbols. - * @return True if some new transition (and sink state) was added to the automaton. - */ -inline bool make_complete(Nfa& aut, const Alphabet& alphabet) { return make_complete(aut, alphabet, aut.num_of_states()); } - /** * @brief Compute automaton accepting complement of @p aut. * diff --git a/include/mata/nfa/plumbing.hh b/include/mata/nfa/plumbing.hh index bcc634cb4..200472028 100644 --- a/include/mata/nfa/plumbing.hh +++ b/include/mata/nfa/plumbing.hh @@ -39,9 +39,6 @@ inline void get_elements(StateSet* element_set, const BoolVector& bool_vec) { } } -/// Make the transition relation complete. -inline void make_complete(Nfa* aut, const Alphabet& alphabet, State sink_state) { make_complete(*aut, alphabet, sink_state); } - inline void complement( Nfa* result, const Nfa& aut, diff --git a/src/nfa/complement.cc b/src/nfa/complement.cc index bbf357128..a8fc509d7 100644 --- a/src/nfa/complement.cc +++ b/src/nfa/complement.cc @@ -48,7 +48,7 @@ Nfa mata::nfa::algorithms::complement_classical(const Nfa& aut, const OrdVector< } } - make_complete(result, symbols, sink_state); + result.make_complete(symbols, sink_state); result.final.complement(result.num_of_states()); return result; } diff --git a/src/nfa/operations.cc b/src/nfa/operations.cc index 2db56d588..114f834bd 100644 --- a/src/nfa/operations.cc +++ b/src/nfa/operations.cc @@ -134,29 +134,29 @@ std::ostream &std::operator<<(std::ostream &os, const mata::nfa::Transition &tra return os << result; } -bool mata::nfa::make_complete(Nfa& aut, const Alphabet& alphabet, State sink_state) { - return mata::nfa::make_complete(aut, alphabet.get_alphabet_symbols(), sink_state); +bool mata::nfa::Nfa::make_complete(const Alphabet& alphabet, State sink_state) { + return this->make_complete(alphabet.get_alphabet_symbols(), sink_state); } -bool mata::nfa::make_complete(Nfa& aut, const mata::utils::OrdVector& symbols, State sink_state) { +bool mata::nfa::Nfa::make_complete(const mata::utils::OrdVector& symbols, State sink_state) { bool was_something_added{ false }; - size_t num_of_states{ aut.num_of_states() }; + size_t num_of_states{ this->num_of_states() }; for (State state = 0; state < num_of_states; ++state) { OrdVector used_symbols{}; - for (auto const &move : aut.delta[state]) { + for (auto const &move : this->delta[state]) { used_symbols.insert(move.symbol); } mata::utils::OrdVector unused_symbols{ symbols.difference(used_symbols) }; for (Symbol symb : unused_symbols) { - aut.delta.add(state, symb, sink_state); + this->delta.add(state, symb, sink_state); was_something_added = true; } } if (was_something_added && num_of_states <= sink_state) { for (Symbol symbol : symbols) { - aut.delta.add(sink_state, symbol, sink_state); + this->delta.add(sink_state, symbol, sink_state); } } diff --git a/tests/nfa/nfa-plumbing.cc b/tests/nfa/nfa-plumbing.cc index f373273b7..547fc60be 100644 --- a/tests/nfa/nfa-plumbing.cc +++ b/tests/nfa/nfa-plumbing.cc @@ -131,9 +131,4 @@ TEST_CASE("Mata::nfa::Plumbing") { mata::nfa::plumbing::complement(&result, lhs, alph); CHECK(!result.is_lang_empty()); } - SECTION("Mata::nfa::Plumbing::make_complete") { - FILL_WITH_AUT_A(lhs); - mata::nfa::plumbing::make_complete(&lhs, alph, lhs.num_of_states() + 1); - CHECK(!lhs.empty_language()); - } } diff --git a/tests/nfa/nfa.cc b/tests/nfa/nfa.cc index 0ee4d0908..653f112a0 100644 --- a/tests/nfa/nfa.cc +++ b/tests/nfa/nfa.cc @@ -823,7 +823,7 @@ TEST_CASE("mata::nfa::make_complete()") { OnTheFlyAlphabet alph{}; - make_complete(aut, alph, 0); + aut.make_complete(alph, 0); REQUIRE(aut.initial.empty()); REQUIRE(aut.final.empty()); @@ -834,7 +834,7 @@ TEST_CASE("mata::nfa::make_complete()") { OnTheFlyAlphabet alph{ std::vector{ "a", "b" } }; - make_complete(aut, alph, 0); + aut.make_complete(alph, 0); REQUIRE(aut.initial.empty()); REQUIRE(aut.final.empty()); @@ -848,7 +848,7 @@ TEST_CASE("mata::nfa::make_complete()") aut.initial = {1}; - make_complete(aut, alphabet, 0); + aut.make_complete(alphabet, 0); REQUIRE(aut.initial.size() == 1); REQUIRE(*aut.initial.begin() == 1); @@ -863,7 +863,7 @@ TEST_CASE("mata::nfa::make_complete()") aut.initial = {1}; - make_complete(aut, alph, SINK); + aut.make_complete(alph, SINK); REQUIRE(aut.initial.size() == 1); REQUIRE(*aut.initial.begin() == 1); @@ -888,7 +888,7 @@ TEST_CASE("mata::nfa::make_complete()") aut.delta.add(3, alph["b"], 5); aut.delta.add(4, alph["c"], 8); - make_complete(aut, alph, SINK); + aut.make_complete(alph, SINK); REQUIRE(aut.delta.contains(1, alph["a"], 2)); REQUIRE(aut.delta.contains(1, alph["b"], SINK)); @@ -1858,7 +1858,7 @@ TEST_CASE("mata::nfa::is_complete()") REQUIRE(!aut.is_complete(&alph)); - make_complete(aut, alph, 100); + aut.make_complete(alph, 100); REQUIRE(aut.is_complete(&alph)); } @@ -2663,7 +2663,7 @@ TEST_CASE("A segmentation fault in the make_complement") { r.initial = {0}; r.delta.add(0, 0, 0); REQUIRE(not r.is_complete(&alph)); - make_complete(r, alph, 1); + r.make_complete(alph, 1); REQUIRE(r.is_complete(&alph)); } From 4fe2e070d5de5ea5c477decfca053430800f67b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 11 Sep 2023 13:35:37 +0200 Subject: [PATCH 22/23] Mark const method as const --- include/mata/nfa/nfa.hh | 2 +- src/nfa/nfa.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mata/nfa/nfa.hh b/include/mata/nfa/nfa.hh index 494bb7b8d..b9962f846 100644 --- a/include/mata/nfa/nfa.hh +++ b/include/mata/nfa/nfa.hh @@ -149,7 +149,7 @@ public: * essentially only useful for testing purposes. * @return True if automata are exactly identical, false otherwise. */ - bool is_identical(const Nfa & aut); + bool is_identical(const Nfa& aut) const; /** * @brief Get set of reachable states. diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index 57c422c6b..bac88cd1d 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -499,7 +499,7 @@ void Nfa::clear() { final.clear(); } -bool Nfa::is_identical(const Nfa& aut) { +bool Nfa::is_identical(const Nfa& aut) const { if (utils::OrdVector(initial) != utils::OrdVector(aut.initial)) { return false; } From f679a26e95526d34610af3775153d34394c33e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Chocholat=C3=BD?= Date: Mon, 18 Sep 2023 07:11:00 +0200 Subject: [PATCH 23/23] Add `uses_state()` to `Delta` --- include/mata/nfa/delta.hh | 5 +++++ src/nfa/nfa.cc | 6 +++--- tests/nfa/delta.cc | 8 ++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/mata/nfa/delta.hh b/include/mata/nfa/delta.hh index 37f7b119a..faa1ab316 100644 --- a/include/mata/nfa/delta.hh +++ b/include/mata/nfa/delta.hh @@ -364,6 +364,11 @@ public: */ size_t num_of_states() const { return state_posts_.size(); } + /** + * Check whether the @p state is used in @c Delta. + */ + bool uses_state(const State state) const { return state < num_of_states(); } + /** * @return Number of transitions in Delta. */ diff --git a/src/nfa/nfa.cc b/src/nfa/nfa.cc index bac88cd1d..32c56ea08 100644 --- a/src/nfa/nfa.cc +++ b/src/nfa/nfa.cc @@ -487,9 +487,9 @@ State Nfa::add_state(State state) { size_t Nfa::num_of_states() const { return std::max({ - static_cast(initial.domain_size()), - static_cast(final.domain_size()), - static_cast(delta.num_of_states()) + static_cast(initial.domain_size()), + static_cast(final.domain_size()), + static_cast(delta.num_of_states()) }); } diff --git a/tests/nfa/delta.cc b/tests/nfa/delta.cc index 2e4c551c2..895766c26 100644 --- a/tests/nfa/delta.cc +++ b/tests/nfa/delta.cc @@ -104,14 +104,22 @@ TEST_CASE("mata::nfa::Delta::mutable_post()") { SECTION("Default initialized") { CHECK(nfa.delta.num_of_states() == 0); + CHECK(!nfa.delta.uses_state(0)); CHECK(nfa.delta.mutable_state_post(0).empty()); CHECK(nfa.delta.num_of_states() == 1); + CHECK(nfa.delta.uses_state(0)); CHECK(nfa.delta.mutable_state_post(9).empty()); CHECK(nfa.delta.num_of_states() == 10); + CHECK(nfa.delta.uses_state(1)); + CHECK(nfa.delta.uses_state(2)); + CHECK(nfa.delta.uses_state(9)); + CHECK(!nfa.delta.uses_state(10)); CHECK(nfa.delta.mutable_state_post(9).empty()); CHECK(nfa.delta.num_of_states() == 10); + CHECK(nfa.delta.uses_state(9)); + CHECK(!nfa.delta.uses_state(10)); } }