diff --git a/iface/dve2/dve2check.cc b/iface/dve2/dve2check.cc index 052771210..821203264 100644 --- a/iface/dve2/dve2check.cc +++ b/iface/dve2/dve2check.cc @@ -157,16 +157,16 @@ checked_main(int argc, char **argv) spot::ltl::atomic_prop_set ap; auto dict = spot::make_bdd_dict(); - spot::const_kripke_ptr model = 0; - spot::const_tgba_ptr prop = 0; - spot::const_tgba_ptr product = 0; - spot::emptiness_check_instantiator* echeck_inst = 0; + spot::const_kripke_ptr model = nullptr; + spot::const_tgba_ptr prop = nullptr; + spot::const_tgba_ptr product = nullptr; + spot::emptiness_check_instantiator_ptr echeck_inst = nullptr; int exit_code = 0; spot::postprocessor post; - const spot::ltl::formula* deadf = 0; - const spot::ltl::formula* f = 0; + const spot::ltl::formula* deadf = nullptr; + const spot::ltl::formula* f = nullptr; - if (dead == 0 || !strcasecmp(dead, "true")) + if (!dead || !strcasecmp(dead, "true")) { deadf = spot::ltl::constant::true_instance(); } @@ -182,8 +182,7 @@ checked_main(int argc, char **argv) if (output == EmptinessCheck) { const char* err; - echeck_inst = - spot::emptiness_check_instantiator::construct(echeck_algo, &err); + echeck_inst = spot::make_emptiness_check_instantiator(echeck_algo, &err); if (!echeck_inst) { std::cerr << "Failed to parse argument of -e/-E near `" @@ -265,14 +264,14 @@ checked_main(int argc, char **argv) assert(echeck_inst); { - spot::emptiness_check* ec = echeck_inst->instantiate(product); + auto ec = echeck_inst->instantiate(product); bool search_many = echeck_inst->options().get("repeated"); assert(ec); do { int memused = spot::memusage(); tm.start("running emptiness check"); - spot::emptiness_check_result* res; + spot::emptiness_check_result_ptr res; try { res = ec->check(); @@ -315,7 +314,7 @@ checked_main(int argc, char **argv) else if (accepting_run) { - spot::tgba_run* run; + spot::tgba_run_ptr run; tm.start("computing accepting run"); try { @@ -337,31 +336,24 @@ checked_main(int argc, char **argv) else { tm.start("reducing accepting run"); - spot::tgba_run* redrun = - spot::reduce_run(res->automaton(), run); + run = spot::reduce_run(res->automaton(), run); tm.stop("reducing accepting run"); - delete run; - run = redrun; tm.start("printing accepting run"); spot::print_tgba_run(std::cout, product, run); tm.stop("printing accepting run"); } - delete run; } else { std::cout << "an accepting run exists " << "(use -C to print it)" << std::endl; } - delete res; } while (search_many); - delete ec; } safe_exit: - delete echeck_inst; if (f) f->destroy(); diff --git a/src/bin/ltlcross.cc b/src/bin/ltlcross.cc index 383f57e40..695a0e094 100644 --- a/src/bin/ltlcross.cc +++ b/src/bin/ltlcross.cc @@ -1071,9 +1071,7 @@ namespace size_t i, size_t j, bool icomp, bool jcomp) { auto prod = spot::product(aut_i, aut_j); - spot::emptiness_check* ec = spot::couvreur99(prod); - spot::emptiness_check_result* res = ec->check(); - + auto res = spot::couvreur99(prod)->check(); if (res) { std::ostream& err = global_error(); @@ -1088,17 +1086,15 @@ namespace err << "*N" << j; err << " is nonempty"; - spot::tgba_run* run = res->accepting_run(); + auto run = res->accepting_run(); if (run) { - const spot::tgba_run* runmin = reduce_run(prod, run); - delete run; + run = reduce_run(prod, run); std::cerr << "; both automata accept the infinite word\n" << " "; - spot::tgba_word w(runmin); + spot::tgba_word w(run); w.simplify(); w.print(example(), prod->get_dict()) << '\n'; - delete runmin; } else { @@ -1106,9 +1102,7 @@ namespace } end_error(); } - delete res; - delete ec; - return res; + return !!res; } static bool diff --git a/src/dstarparse/dra2ba.cc b/src/dstarparse/dra2ba.cc index 83ba45898..fe41b347f 100644 --- a/src/dstarparse/dra2ba.cc +++ b/src/dstarparse/dra2ba.cc @@ -148,18 +148,10 @@ namespace spot { state_set keep(sl.begin(), sl.end()); auto masked = build_tgba_mask_keep(dra->aut, keep, sl.front()); - emptiness_check* ec = couvreur99(nra_to_nba(dra, masked)); - emptiness_check_result* ecr = ec->check(); - delete ecr; - delete ec; - if (ecr) - { - // This SCC is not DBA-realizable. - //std::cerr << "not DBA-realizable\n"; - return false; - } + if (!nra_to_nba(dra, masked)->is_empty()) + // This SCC is not DBA-realizable. + return false; } - //std::cerr << "non-accepting\n"; for (state_list::const_iterator i = sl.begin(); i != sl.end(); ++i) nonfinal.push_back(*i); diff --git a/src/ltlvisit/contain.cc b/src/ltlvisit/contain.cc index f083f3c3e..bef1848c8 100644 --- a/src/ltlvisit/contain.cc +++ b/src/ltlvisit/contain.cc @@ -69,21 +69,10 @@ namespace spot if (i != l->incompatible.end()) return i->second; - auto ec = couvreur99(product(l->translation, g->translation)); - auto ecr = ec->check(); - if (!ecr) - { - l->incompatible[g] = true; - g->incompatible[l] = true; - } - else - { - l->incompatible[g] = false; - g->incompatible[l] = false; - delete ecr; - } - delete ec; - return !ecr; + bool res = product(l->translation, g->translation)->is_empty(); + l->incompatible[g] = res; + g->incompatible[l] = res; + return res; } diff --git a/src/tgba/tgba.cc b/src/tgba/tgba.cc index 6f957edee..89bc1b00e 100644 --- a/src/tgba/tgba.cc +++ b/src/tgba/tgba.cc @@ -21,6 +21,7 @@ // along with this program. If not, see . #include "tgba.hh" +#include "tgbaalgos/gtec/gtec.hh" namespace spot { @@ -85,4 +86,13 @@ namespace spot return num_acc_; } + bool + tgba::is_empty() const + { + // FIXME: This should be improved based on properties of the + // automaton. For instance we do not need couvreur99 is we know + // the automaton is weak. + return !couvreur99(shared_from_this())->check(); + } + } diff --git a/src/tgba/tgba.hh b/src/tgba/tgba.hh index c292b30d2..532323285 100644 --- a/src/tgba/tgba.hh +++ b/src/tgba/tgba.hh @@ -27,7 +27,6 @@ #include "fwd.hh" #include #include -#include #include "misc/casts.hh" #include "misc/hash.hh" @@ -465,7 +464,7 @@ namespace spot /// we never represent transitions! Transition informations are /// obtained by querying the iterator over the successors of /// a state. - class SPOT_API tgba + class SPOT_API tgba: public std::enable_shared_from_this { protected: tgba(); @@ -641,6 +640,8 @@ namespace spot /// the other operand. virtual bdd neg_acceptance_conditions() const = 0; + virtual bool is_empty() const; + protected: /// Do the actual computation of tgba::support_conditions(). virtual bdd compute_support_conditions(const state* state) const = 0; diff --git a/src/tgbaalgos/emptiness.cc b/src/tgbaalgos/emptiness.cc index 524faccb0..808a7e4da 100644 --- a/src/tgbaalgos/emptiness.cc +++ b/src/tgbaalgos/emptiness.cc @@ -77,8 +77,8 @@ namespace spot std::ostream& print_tgba_run(std::ostream& os, - const_tgba_ptr a, - const tgba_run* run) + const const_tgba_ptr& a, + const const_tgba_run_ptr& run) { bdd_dict_ptr d = a->get_dict(); os << "Prefix:" << std::endl; @@ -109,10 +109,10 @@ namespace spot // emptiness_check_result ////////////////////////////////////////////////////////////////////// - tgba_run* + tgba_run_ptr emptiness_check_result::accepting_run() { - return 0; + return nullptr; } const unsigned_statistics* @@ -149,6 +149,12 @@ namespace spot return dynamic_cast(this); } + const ec_statistics* + emptiness_check::emptiness_check_statistics() const + { + return dynamic_cast(this); + } + const char* emptiness_check::parse_options(char* options) { @@ -180,29 +186,23 @@ namespace spot namespace { - emptiness_check* - make_couvreur99(const const_tgba_ptr& a, spot::option_map o) - { - return couvreur99(a, o); - } - struct ec_algo { const char* name; - spot::emptiness_check* (*construct)(const const_tgba_ptr&, - spot::option_map); + emptiness_check_ptr(*construct)(const const_tgba_ptr&, + spot::option_map); unsigned int min_acc; unsigned int max_acc; }; ec_algo ec_algos[] = { - { "Cou99", make_couvreur99, 0, -1U }, - { "CVWY90", spot::magic_search, 0, 1 }, - { "GV04", spot::explicit_gv04_check, 0, 1 }, - { "SE05", spot::se05, 0, 1 }, - { "Tau03", spot::explicit_tau03_search, 1, -1U }, - { "Tau03_opt", spot::explicit_tau03_opt_search, 0, -1U }, + { "Cou99", couvreur99, 0, -1U }, + { "CVWY90", magic_search, 0, 1 }, + { "GV04", explicit_gv04_check, 0, 1 }, + { "SE05", se05, 0, 1 }, + { "Tau03", explicit_tau03_search, 1, -1U }, + { "Tau03_opt", explicit_tau03_opt_search, 0, -1U }, }; } @@ -224,14 +224,14 @@ namespace spot return static_cast(info_)->max_acc; } - emptiness_check* + emptiness_check_ptr emptiness_check_instantiator::instantiate(const const_tgba_ptr& a) const { return static_cast(info_)->construct(a, o_); } - emptiness_check_instantiator* - emptiness_check_instantiator::construct(const char* name, const char** err) + emptiness_check_instantiator_ptr + make_emptiness_check_instantiator(const char* name, const char** err) { // Skip spaces. while (*name && strchr(" \t\n", *name)) @@ -272,17 +272,26 @@ namespace spot if (n == info->name) { *err = 0; - return new emptiness_check_instantiator(o, info); + + struct emptiness_check_instantiator_aux: + public emptiness_check_instantiator + { + emptiness_check_instantiator_aux(option_map o, void* i): + emptiness_check_instantiator(o, i) + { + } + }; + return std::make_shared(o, info); } *err = name; - return 0; + return nullptr; } // tgba_run_to_tgba ////////////////////////////////////////////////////////////////////// tgba_digraph_ptr - tgba_run_to_tgba(const const_tgba_ptr& a, const tgba_run* run) + tgba_run_to_tgba(const const_tgba_ptr& a, const const_tgba_run_ptr& run) { auto d = a->get_dict(); auto res = make_tgba_digraph(d); diff --git a/src/tgbaalgos/emptiness.hh b/src/tgbaalgos/emptiness.hh index 51e1a3387..d3fab5e3c 100644 --- a/src/tgbaalgos/emptiness.hh +++ b/src/tgbaalgos/emptiness.hh @@ -34,6 +34,8 @@ namespace spot { struct tgba_run; + typedef std::shared_ptr tgba_run_ptr; + typedef std::shared_ptr const_tgba_run_ptr; /// \addtogroup emptiness_check Emptiness-checks /// \ingroup tgba_algorithms @@ -99,7 +101,7 @@ namespace spot /// cannot produce a counter example (that does not mean there /// is no counter-example; the mere existence of an instance of /// this class asserts the existence of a counter-example). - virtual tgba_run* accepting_run(); + virtual tgba_run_ptr accepting_run(); /// The automaton on which an accepting_run() was found. const const_tgba_ptr& @@ -129,8 +131,11 @@ namespace spot option_map o_; ///< The options. }; + typedef std::shared_ptr emptiness_check_result_ptr; + /// Common interface to emptiness check algorithms. - class SPOT_API emptiness_check + class SPOT_API emptiness_check: + public std::enable_shared_from_this { public: emptiness_check(const const_tgba_ptr& a, option_map o = option_map()) @@ -173,11 +178,14 @@ namespace spot /// Some emptiness_check algorithms, especially those using bit state /// hashing may return 0 even if the automaton is not empty. /// \see safe() - virtual emptiness_check_result* check() = 0; + virtual emptiness_check_result_ptr check() = 0; /// Return statistics, if available. virtual const unsigned_statistics* statistics() const; + /// Return emptiness check statistics, if available. + virtual const ec_statistics* emptiness_check_statistics() const; + /// Print statistics, if any. virtual std::ostream& print_stats(std::ostream& os) const; @@ -189,25 +197,18 @@ namespace spot option_map o_; ///< The options }; + typedef std::shared_ptr emptiness_check_ptr; + + class emptiness_check_instantiator; + typedef std::shared_ptr + emptiness_check_instantiator_ptr; // Dynamically create emptiness checks. Given their name and options. class SPOT_API emptiness_check_instantiator { public: - /// \brief Create an emptiness-check instantiator, given the name - /// of an emptiness check. - /// - /// \a name should have the form \c "name" or \c "name(options)". - /// - /// On error, the function returns 0. If the name of the algorithm - /// was unknown, \c *err will be set to \c name. If some fragment of - /// the options could not be parsed, \c *err will point to that - /// fragment. - static emptiness_check_instantiator* construct(const char* name, - const char** err); - /// Actually instantiate the emptiness check, for \a a. - emptiness_check* instantiate(const const_tgba_ptr& a) const; + emptiness_check_ptr instantiate(const const_tgba_ptr& a) const; /// Accessor to the options. /// @{ @@ -233,15 +234,27 @@ namespace spot /// /// \return \c -1U if no upper bound exists. unsigned int max_acceptance_conditions() const; - private: + protected: emptiness_check_instantiator(option_map o, void* i); + option_map o_; void *info_; }; - - /// @} + /// \brief Create an emptiness-check instantiator, given the name + /// of an emptiness check. + /// + /// \a name should have the form \c "name" or \c "name(options)". + /// + /// On error, the function returns 0. If the name of the algorithm + /// was unknown, \c *err will be set to \c name. If some fragment of + /// the options could not be parsed, \c *err will point to that + /// fragment. + SPOT_API emptiness_check_instantiator_ptr + make_emptiness_check_instantiator(const char* name, const char** err); + + /// \addtogroup emptiness_check_algorithms Emptiness-check algorithms /// \ingroup emptiness_check @@ -287,14 +300,16 @@ namespace spot /// actually exists in the automaton (and will also display any /// transition annotation). SPOT_API std::ostream& - print_tgba_run(std::ostream& os, const_tgba_ptr a, const tgba_run* run); + print_tgba_run(std::ostream& os, + const const_tgba_ptr& a, + const const_tgba_run_ptr& run); /// \brief Return an explicit_tgba corresponding to \a run (i.e. comparable /// states are merged). /// /// \pre \a run must correspond to an actual run of the automaton \a a. SPOT_API tgba_digraph_ptr - tgba_run_to_tgba(const const_tgba_ptr& a, const tgba_run* run); + tgba_run_to_tgba(const const_tgba_ptr& a, const const_tgba_run_ptr& run); /// @} diff --git a/src/tgbaalgos/gtec/ce.cc b/src/tgbaalgos/gtec/ce.cc index 4c42b236e..59c77c9bf 100644 --- a/src/tgbaalgos/gtec/ce.cc +++ b/src/tgbaalgos/gtec/ce.cc @@ -32,7 +32,7 @@ namespace spot { public: shortest_path(const state_set* t, - const couvreur99_check_status* ecs, + const std::shared_ptr& ecs, couvreur99_check_result* r) : bfs_steps(ecs->aut), target(t), ecs(ecs), r(r) { @@ -68,13 +68,14 @@ namespace spot private: state_set seen; const state_set* target; - const couvreur99_check_status* ecs; + std::shared_ptr ecs; couvreur99_check_result* r; }; } couvreur99_check_result::couvreur99_check_result - (const couvreur99_check_status* ecs, option_map o) + (const std::shared_ptr& ecs, + option_map o) : emptiness_check_result(ecs->aut, o), ecs_(ecs) { } @@ -90,10 +91,10 @@ namespace spot return count; } - tgba_run* + tgba_run_ptr couvreur99_check_result::accepting_run() { - run_ = new tgba_run; + run_ = std::make_shared(); assert(!ecs_->root.empty()); @@ -212,7 +213,7 @@ namespace spot return false; } - } b(ecs_, this, acc_to_traverse); + } b(ecs_.get(), this, acc_to_traverse); substart = b.search(substart, run_->cycle); assert(substart); diff --git a/src/tgbaalgos/gtec/ce.hh b/src/tgbaalgos/gtec/ce.hh index 9a6c7fce9..4975056e3 100644 --- a/src/tgbaalgos/gtec/ce.hh +++ b/src/tgbaalgos/gtec/ce.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2013 Laboratoire de Recherche et Développement de +// Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement de // l'Epita (LRDE). // Copyright (C) 2004, 2005 Laboratoire d'Informatique de Paris 6 (LIP6), // département Systèmes Répartis Coopératifs (SRC), Université Pierre @@ -35,10 +35,11 @@ namespace spot public acss_statistics { public: - couvreur99_check_result(const couvreur99_check_status* ecs, + couvreur99_check_result(const + std::shared_ptr& ecs, option_map o = option_map()); - virtual tgba_run* accepting_run(); + virtual tgba_run_ptr accepting_run(); void print_stats(std::ostream& os) const; @@ -50,8 +51,8 @@ namespace spot void accepting_cycle(); private: - const couvreur99_check_status* ecs_; - tgba_run* run_; + std::shared_ptr ecs_; + tgba_run_ptr run_; }; } diff --git a/src/tgbaalgos/gtec/gtec.cc b/src/tgbaalgos/gtec/gtec.cc index 3d47ccca4..ab22a6d30 100644 --- a/src/tgbaalgos/gtec/gtec.cc +++ b/src/tgbaalgos/gtec/gtec.cc @@ -45,7 +45,7 @@ namespace spot removed_components(0) { poprem_ = o.get("poprem", 1); - ecs_ = new couvreur99_check_status(a); + ecs_ = std::make_shared(a); stats["removed components"] = static_cast (&couvreur99_check::get_removed_components); @@ -56,7 +56,6 @@ namespace spot couvreur99_check::~couvreur99_check() { - delete ecs_; } unsigned @@ -129,7 +128,7 @@ namespace spot } } - emptiness_check_result* + emptiness_check_result_ptr couvreur99_check::check() { // We use five main data in this algorithm: @@ -281,15 +280,15 @@ namespace spot // cycle. ecs_->cycle_seed = p.first->first; set_states(ecs_->states()); - return new couvreur99_check_result(ecs_, options()); + return std::make_shared(ecs_, options()); } } // This automaton recognizes no word. set_states(ecs_->states()); - return 0; + return nullptr; } - const couvreur99_check_status* + std::shared_ptr couvreur99_check::result() const { return ecs_; @@ -383,7 +382,7 @@ namespace spot } } - emptiness_check_result* + emptiness_check_result_ptr couvreur99_check_shy::check() { // Position in the loop seeking known successors. @@ -418,7 +417,7 @@ namespace spot // This automaton recognizes no word. set_states(ecs_->states()); assert(poprem_ || depth() == 0); - return 0; + return nullptr; } pos = todo.back().q.begin(); @@ -554,7 +553,7 @@ namespace spot // We have found an accepting SCC. Clean up TODO. clear_todo(); set_states(ecs_->states()); - return new couvreur99_check_result(ecs_, options()); + return std::make_shared(ecs_, options()); } // Group the pending successors of formed SCC if requested. if (group_) @@ -592,12 +591,12 @@ namespace spot } } - emptiness_check* + emptiness_check_ptr couvreur99(const const_tgba_ptr& a, option_map o) { if (o.get("shy")) - return new couvreur99_check_shy(a, o); - return new couvreur99_check(a, o); + return std::make_shared(a, o); + return std::make_shared(a, o); } } diff --git a/src/tgbaalgos/gtec/gtec.hh b/src/tgbaalgos/gtec/gtec.hh index 909e1f145..7a42cb2cc 100644 --- a/src/tgbaalgos/gtec/gtec.hh +++ b/src/tgbaalgos/gtec/gtec.hh @@ -136,10 +136,10 @@ namespace spot /// states that belong to the same SCC will be considered when /// choosing a successor. Otherwise, only the successor of the /// topmost state on the DFS stack are considered. - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr couvreur99(const const_tgba_ptr& a, option_map options = option_map()); - +#ifndef SWIG /// \brief An implementation of the Couvreur99 emptiness-check algorithm. /// /// See the documentation for spot::couvreur99. @@ -150,7 +150,7 @@ namespace spot virtual ~couvreur99_check(); /// Check whether the automaton's language is empty. - virtual emptiness_check_result* check(); + virtual emptiness_check_result_ptr check(); virtual std::ostream& print_stats(std::ostream& os) const; @@ -162,10 +162,10 @@ namespace spot /// This status should not be deleted, it is a pointer /// to a member of this class that will be deleted when /// the couvreur99 object is deleted. - const couvreur99_check_status* result() const; + std::shared_ptr result() const; protected: - couvreur99_check_status* ecs_; + std::shared_ptr ecs_; /// \brief Remove a strongly component from the hash. /// /// This function remove all accessible state from a given @@ -191,7 +191,7 @@ namespace spot couvreur99_check_shy(const const_tgba_ptr& a, option_map o = option_map()); virtual ~couvreur99_check_shy(); - virtual emptiness_check_result* check(); + virtual emptiness_check_result_ptr check(); protected: struct successor { @@ -239,7 +239,7 @@ namespace spot // reprocess the successor states of SCC that have been merged. bool group2_; }; - +#endif /// @} } diff --git a/src/tgbaalgos/gv04.cc b/src/tgbaalgos/gv04.cc index 757d6e013..42a5aa6b3 100644 --- a/src/tgbaalgos/gv04.cc +++ b/src/tgbaalgos/gv04.cc @@ -91,7 +91,7 @@ namespace spot } } - virtual emptiness_check_result* + virtual emptiness_check_result_ptr check() { top = dftop = -1; @@ -162,7 +162,7 @@ namespace spot set_states(h.size()); } if (violation) - return new result(*this); + return std::make_shared(*this); return 0; } @@ -287,10 +287,10 @@ namespace spot return s; } - virtual tgba_run* + virtual tgba_run_ptr accepting_run() { - tgba_run* res = new tgba_run; + auto res = std::make_shared(); update_lowlinks(); #ifdef TRACE @@ -409,9 +409,9 @@ namespace spot } // anonymous - emptiness_check* + emptiness_check_ptr explicit_gv04_check(const const_tgba_ptr& a, option_map o) { - return new gv04(a, o); + return std::make_shared(a, o); } } diff --git a/src/tgbaalgos/gv04.hh b/src/tgbaalgos/gv04.hh index 4325dc889..0b9ce7d66 100644 --- a/src/tgbaalgos/gv04.hh +++ b/src/tgbaalgos/gv04.hh @@ -25,11 +25,10 @@ # include "misc/optionmap.hh" # include "tgba/fwd.hh" +# include "emptiness.hh" namespace spot { - class emptiness_check; - /// \brief Emptiness check based on Geldenhuys and Valmari's /// TACAS'04 paper. /// \ingroup emptiness_check_algorithms @@ -54,7 +53,7 @@ namespace spot isbn = {3-540-21299-X} } \endverbatim */ - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr explicit_gv04_check(const const_tgba_ptr& a, option_map o = option_map()); } diff --git a/src/tgbaalgos/magic.cc b/src/tgbaalgos/magic.cc index 613eb52fa..8f7a28349 100644 --- a/src/tgbaalgos/magic.cc +++ b/src/tgbaalgos/magic.cc @@ -88,8 +88,10 @@ namespace spot /// check() can be called several times (until it returns a null /// pointer) to enumerate all the visited accepting paths. The method /// visits only a finite set of accepting paths. - virtual emptiness_check_result* check() + virtual emptiness_check_result_ptr check() { + auto t = std::static_pointer_cast + (this->emptiness_check::shared_from_this()); if (st_red.empty()) { assert(st_blue.empty()); @@ -98,19 +100,19 @@ namespace spot h.add_new_state(s0, BLUE); push(st_blue, s0, bddfalse, bddfalse); if (dfs_blue()) - return new magic_search_result(*this, options()); + return std::make_shared(t, options()); } else { h.pop_notify(st_red.front().s); pop(st_red); if (!st_red.empty() && dfs_red()) - return new magic_search_result(*this, options()); + return std::make_shared(t, options()); else if (dfs_blue()) - return new magic_search_result(*this, options()); + return std::make_shared(t, options()); } - return 0; + return nullptr; } virtual std::ostream& print_stats(std::ostream &os) const @@ -325,25 +327,25 @@ namespace spot public acss_statistics { public: - result_from_stack(magic_search_& ms) - : emptiness_check_result(ms.automaton()), ms_(ms) + result_from_stack(std::shared_ptr ms) + : emptiness_check_result(ms->automaton()), ms_(ms) { } - virtual tgba_run* accepting_run() + virtual tgba_run_ptr accepting_run() { - assert(!ms_.st_blue.empty()); - assert(!ms_.st_red.empty()); + assert(!ms_->st_blue.empty()); + assert(!ms_->st_red.empty()); - tgba_run* run = new tgba_run; + auto run = std::make_shared(); typename stack_type::const_reverse_iterator i, j, end; tgba_run::steps* l; l = &run->prefix; - i = ms_.st_blue.rbegin(); - end = ms_.st_blue.rend(); --end; + i = ms_->st_blue.rbegin(); + end = ms_->st_blue.rend(); --end; j = i; ++j; for (; i != end; ++i, ++j) { @@ -353,12 +355,12 @@ namespace spot l = &run->cycle; - j = ms_.st_red.rbegin(); + j = ms_->st_red.rbegin(); tgba_run::step s = { i->s->clone(), j->label, j->acc }; l->push_back(s); i = j; ++j; - end = ms_.st_red.rend(); --end; + end = ms_->st_red.rend(); --end; for (; i != end; ++i, ++j) { tgba_run::step s = { i->s->clone(), j->label, j->acc }; @@ -373,7 +375,7 @@ namespace spot return 0; } private: - magic_search_& ms_; + std::shared_ptr ms_; }; # define FROM_STACK "ar:from_stack" @@ -381,8 +383,9 @@ namespace spot class magic_search_result: public emptiness_check_result { public: - magic_search_result(magic_search_& m, option_map o = option_map()) - : emptiness_check_result(m.automaton(), o), ms(m) + magic_search_result(const std::shared_ptr& m, + option_map o = option_map()) + : emptiness_check_result(m->automaton(), o), ms(m) { if (options()[FROM_STACK]) computer = new result_from_stack(ms); @@ -409,7 +412,7 @@ namespace spot delete computer; } - virtual tgba_run* accepting_run() + virtual tgba_run_ptr accepting_run() { return computer->accepting_run(); } @@ -421,7 +424,7 @@ namespace spot private: emptiness_check_result* computer; - magic_search_& ms; + std::shared_ptr ms; }; }; @@ -584,18 +587,20 @@ namespace spot } // anonymous - emptiness_check* explicit_magic_search(const const_tgba_ptr& a, option_map o) + emptiness_check_ptr + explicit_magic_search(const const_tgba_ptr& a, option_map o) { - return new magic_search_(a, 0, o); + return std::make_shared>(a, 0, o); } - emptiness_check* bit_state_hashing_magic_search(const const_tgba_ptr& a, - size_t size, option_map o) + emptiness_check_ptr + bit_state_hashing_magic_search(const const_tgba_ptr& a, + size_t size, option_map o) { - return new magic_search_(a, size, o); + return std::make_shared>(a, size, o); } - emptiness_check* + emptiness_check_ptr magic_search(const const_tgba_ptr& a, option_map o) { size_t size = o.get("bsh"); diff --git a/src/tgbaalgos/magic.hh b/src/tgbaalgos/magic.hh index be6967b94..de7e84bb7 100644 --- a/src/tgbaalgos/magic.hh +++ b/src/tgbaalgos/magic.hh @@ -26,11 +26,10 @@ #include #include "tgba/fwd.hh" #include "misc/optionmap.hh" +#include "emptiness.hh" namespace spot { - class emptiness_check; - /// \addtogroup emptiness_check_algorithms /// @{ @@ -97,7 +96,7 @@ namespace spot /// /// \bug The name is misleading. Magic-search is the algorithm /// from \c godefroid.93.pstv, not \c courcoubetis.92.fmsd. - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr explicit_magic_search(const const_tgba_ptr& a, option_map o = option_map()); @@ -128,7 +127,7 @@ namespace spot /// /// \sa spot::explicit_magic_search /// - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr bit_state_hashing_magic_search(const const_tgba_ptr& a, size_t size, option_map o = option_map()); @@ -138,7 +137,7 @@ namespace spot /// bit_state_hashing_magic_search() according to the \c "bsh" option /// in the \c option_map. If \c "bsh" is set and non null, its value /// is used as the size of the hash map. - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr magic_search(const const_tgba_ptr& a, option_map o = option_map()); /// @} diff --git a/src/tgbaalgos/minimize.cc b/src/tgbaalgos/minimize.cc index 9b6c82c9c..1e4034fd9 100644 --- a/src/tgbaalgos/minimize.cc +++ b/src/tgbaalgos/minimize.cc @@ -260,13 +260,7 @@ namespace spot // Contrustruct a product between // LOOP_A, and ORIG_A starting in *IT. // FIXME: This could be sped up a lot! - emptiness_check* ec = couvreur99(product_at(loop_a, orig_a, - loop_a_init, it)); - emptiness_check_result* res = ec->check(); - delete res; - delete ec; - - if (res) + if (!product_at(loop_a, orig_a, loop_a_init, it)->is_empty()) { accepting = true; break; @@ -674,25 +668,15 @@ namespace spot bool ok = false; - emptiness_check* ec = couvreur99(product(min_aut_f, aut_neg_f)); - emptiness_check_result* res = ec->check(); - if (!res) + if (product(min_aut_f, aut_neg_f)->is_empty()) { - delete ec; - // Complement the minimized WDBA. auto neg_min_aut_f = wdba_complement(min_aut_f); - ec = couvreur99(product(aut_f, neg_min_aut_f)); - res = ec->check(); - if (!res) - { - // Finally, we are now sure that it was safe - // to minimize the automaton. - ok = true; - } + if (product(aut_f, neg_min_aut_f)->is_empty()) + // Finally, we are now sure that it was safe + // to minimize the automaton. + ok = true; } - delete res; - delete ec; if (ok) return min_aut_f; diff --git a/src/tgbaalgos/ndfs_result.hxx b/src/tgbaalgos/ndfs_result.hxx index 90e8d2f7c..70a3a47b7 100644 --- a/src/tgbaalgos/ndfs_result.hxx +++ b/src/tgbaalgos/ndfs_result.hxx @@ -95,9 +95,9 @@ namespace spot public stats_interface, heap::Has_Size> { public: - ndfs_result(const ndfs_search& ms) - : emptiness_check_result(ms.automaton()), ms_(ms), - h_(ms_.get_heap()) + ndfs_result(const std::shared_ptr& ms) + : emptiness_check_result(ms->automaton()), ms_(ms), + h_(ms->get_heap()) { } @@ -105,10 +105,10 @@ namespace spot { } - virtual tgba_run* accepting_run() + virtual tgba_run_ptr accepting_run() { - const stack_type& stb = ms_.get_st_blue(); - const stack_type& str = ms_.get_st_red(); + const stack_type& stb = ms_->get_st_blue(); + const stack_type& str = ms_->get_st_red(); assert(!stb.empty()); @@ -195,7 +195,7 @@ namespace spot assert(!acc_trans.empty()); - tgba_run* run = new tgba_run; + auto run = std::make_shared(); // construct run->cycle from acc_trans. construct_cycle(run, acc_trans); // construct run->prefix (a minimal path from the initial state to any @@ -214,7 +214,7 @@ namespace spot } private: - const ndfs_search& ms_; + std::shared_ptr ms_; const heap& h_; template friend struct stats_interface; @@ -529,7 +529,7 @@ namespace spot const heap& h; }; - void construct_cycle(tgba_run* run, + void construct_cycle(tgba_run_ptr run, const accepting_transitions_list& acc_trans) { assert(!acc_trans.empty()); @@ -616,7 +616,7 @@ namespace spot } } - void construct_prefix(tgba_run* run) + void construct_prefix(tgba_run_ptr run) { m_source_trans target; transition tmp; diff --git a/src/tgbaalgos/powerset.cc b/src/tgbaalgos/powerset.cc index f41cf4770..acd92dde4 100644 --- a/src/tgbaalgos/powerset.cc +++ b/src/tgbaalgos/powerset.cc @@ -205,11 +205,7 @@ namespace spot { // Check the product between LOOP_A, and ORIG_A starting // in S. - auto ec = couvreur99(product_at(loop_a, ref_, loop_a_init, s)); - emptiness_check_result* res = ec->check(); - delete res; - delete ec; - if (res) + if (!product_at(loop_a, ref_, loop_a_init, s)->is_empty()) { accepting = true; break; @@ -326,9 +322,9 @@ namespace spot auto det = tba_determinize(aut, threshold_states, threshold_cycles); if (!det) - return 0; + return nullptr; - if (neg_aut == 0) + if (neg_aut == nullptr) { const ltl::formula* neg_f = ltl::unop::instance(ltl::unop::Not, f->clone()); @@ -339,30 +335,13 @@ namespace spot neg_aut = scc_filter(neg_aut, true); } - bool ok = false; + if (product(det, neg_aut)->is_empty()) + // Complement the DBA. + if (product(aut, dtgba_complement(det))->is_empty()) + // Finally, we are now sure that it was safe + // to determinize the automaton. + return det; - auto ec = couvreur99(product(det, neg_aut)); - auto res = ec->check(); - if (!res) - { - delete ec; - - // Complement the DBA. - ec = couvreur99(product(aut, dtgba_complement(det))); - res = ec->check(); - - if (!res) - { - // Finally, we are now sure that it was safe - // to determinize the automaton. - ok = true; - } - } - delete res; - delete ec; - - if (ok) - return det; return aut; } } diff --git a/src/tgbaalgos/projrun.cc b/src/tgbaalgos/projrun.cc index fb140be47..278b42b65 100644 --- a/src/tgbaalgos/projrun.cc +++ b/src/tgbaalgos/projrun.cc @@ -24,12 +24,12 @@ namespace spot { - tgba_run* + tgba_run_ptr project_tgba_run(const const_tgba_ptr& a_run, const const_tgba_ptr& a_proj, - const tgba_run* run) + const const_tgba_run_ptr& run) { - tgba_run* res = new tgba_run; + auto res = std::make_shared(); for (tgba_run::steps::const_iterator i = run->prefix.begin(); i != run->prefix.end(); ++i) { diff --git a/src/tgbaalgos/projrun.hh b/src/tgbaalgos/projrun.hh index 92b9a9570..a43dcca2e 100644 --- a/src/tgbaalgos/projrun.hh +++ b/src/tgbaalgos/projrun.hh @@ -26,6 +26,7 @@ # include "misc/common.hh" # include # include "tgba/fwd.hh" +# include "tgbaalgos/emptiness.hh" namespace spot { @@ -41,10 +42,10 @@ namespace spot /// \param a_run the automata on which the run was generated /// \param a_proj the automata on which to project the run /// \return true iff the run could be completed - SPOT_API tgba_run* + SPOT_API tgba_run_ptr project_tgba_run(const const_tgba_ptr& a_run, const const_tgba_ptr& a_proj, - const tgba_run* run); + const const_tgba_run_ptr& run); } #endif // SPOT_TGBAALGOS_PROJRUN_HH diff --git a/src/tgbaalgos/reducerun.cc b/src/tgbaalgos/reducerun.cc index ce4381625..c1f02549a 100644 --- a/src/tgbaalgos/reducerun.cc +++ b/src/tgbaalgos/reducerun.cc @@ -1,7 +1,8 @@ -// Copyright (C) 2011, 2013 Laboratoire de Recherche et Développement -// de l'Epita (LRDE). +// -*- coding: utf-8 -*- +// Copyright (C) 2011, 2013, 2014 Laboratoire de Recherche et +// Développement de l'Epita (LRDE). // Copyright (C) 2004 Laboratoire d'Informatique de Paris 6 (LIP6), -// département Systèmes Répartis Coopératifs (SRC), Université Pierre +// département Systèmes Répartis Coopératifs (SRC), Université Pierre // et Marie Curie. // // This file is part of Spot, a model checking library. @@ -86,10 +87,10 @@ namespace spot }; } - tgba_run* - reduce_run(const const_tgba_ptr& a, const tgba_run* org) + tgba_run_ptr + reduce_run(const const_tgba_ptr& a, const const_tgba_run_ptr& org) { - tgba_run* res = new tgba_run; + auto res = std::make_shared(); state_set ss; shortest_path shpath(a); shpath.set_target(&ss); diff --git a/src/tgbaalgos/reducerun.hh b/src/tgbaalgos/reducerun.hh index 9dadcef29..4a251f22c 100644 --- a/src/tgbaalgos/reducerun.hh +++ b/src/tgbaalgos/reducerun.hh @@ -25,18 +25,17 @@ # include "misc/common.hh" # include "tgba/fwd.hh" +# include "tgbaalgos/emptiness.hh" namespace spot { - struct tgba_run; - /// \ingroup tgba_run /// \brief Reduce an accepting run. /// /// Return a run which is accepting for \a a and that is no longer /// than \a org. - SPOT_API tgba_run* - reduce_run(const const_tgba_ptr& a, const tgba_run* org); + SPOT_API tgba_run_ptr + reduce_run(const const_tgba_ptr& a, const const_tgba_run_ptr& org); } #endif // SPOT_TGBAALGOS_REDUCERUN_HH diff --git a/src/tgbaalgos/replayrun.cc b/src/tgbaalgos/replayrun.cc index b5d9a06b3..52ba65379 100644 --- a/src/tgbaalgos/replayrun.cc +++ b/src/tgbaalgos/replayrun.cc @@ -32,7 +32,8 @@ namespace spot namespace { void - print_annotation(std::ostream& os, const_tgba_ptr a, + print_annotation(std::ostream& os, + const const_tgba_ptr& a, const tgba_succ_iterator* i) { std::string s = a->transition_annotation(i); @@ -44,7 +45,7 @@ namespace spot bool replay_tgba_run(std::ostream& os, const const_tgba_ptr& a, - const tgba_run* run, bool debug) + const const_tgba_run_ptr& run, bool debug) { const state* s = a->get_init_state(); int serial = 1; diff --git a/src/tgbaalgos/replayrun.hh b/src/tgbaalgos/replayrun.hh index 1f6ad50dc..169685dd7 100644 --- a/src/tgbaalgos/replayrun.hh +++ b/src/tgbaalgos/replayrun.hh @@ -26,6 +26,7 @@ # include "misc/common.hh" # include # include "tgba/fwd.hh" +# include "tgbaalgos/emptiness.hh" namespace spot { @@ -48,7 +49,8 @@ namespace spot /// \return true iff the run could be completed SPOT_API bool replay_tgba_run(std::ostream& os, - const const_tgba_ptr& a, const tgba_run* run, + const const_tgba_ptr& a, + const const_tgba_run_ptr& run, bool debug = false); } diff --git a/src/tgbaalgos/rundotdec.cc b/src/tgbaalgos/rundotdec.cc index 826403fe6..17a604887 100644 --- a/src/tgbaalgos/rundotdec.cc +++ b/src/tgbaalgos/rundotdec.cc @@ -26,7 +26,8 @@ namespace spot { - tgba_run_dotty_decorator::tgba_run_dotty_decorator(const tgba_run* run) + tgba_run_dotty_decorator::tgba_run_dotty_decorator(const + const_tgba_run_ptr& run) : run_(run) { int n = 1; diff --git a/src/tgbaalgos/rundotdec.hh b/src/tgbaalgos/rundotdec.hh index cad77251a..433f30314 100644 --- a/src/tgbaalgos/rundotdec.hh +++ b/src/tgbaalgos/rundotdec.hh @@ -38,7 +38,7 @@ namespace spot class SPOT_API tgba_run_dotty_decorator: public dotty_decorator { public: - tgba_run_dotty_decorator(const tgba_run* run); + tgba_run_dotty_decorator(const const_tgba_run_ptr& run); virtual ~tgba_run_dotty_decorator(); virtual std::string state_decl(const const_tgba_ptr& a, @@ -52,7 +52,7 @@ namespace spot const tgba_succ_iterator* si, const std::string& label); private: - const tgba_run* run_; + const_tgba_run_ptr run_; typedef std::pair step_num; typedef std::list step_set; typedef std::map, diff --git a/src/tgbaalgos/se05.cc b/src/tgbaalgos/se05.cc index 2f2381978..ccc0b71c6 100644 --- a/src/tgbaalgos/se05.cc +++ b/src/tgbaalgos/se05.cc @@ -88,8 +88,10 @@ namespace spot /// check() can be called several times (until it returns a null /// pointer) to enumerate all the visited accepting paths. The method /// visits only a finite set of accepting paths. - virtual emptiness_check_result* check() + virtual emptiness_check_result_ptr check() { + auto t = std::static_pointer_cast + (this->emptiness_check::shared_from_this()); if (st_red.empty()) { assert(st_blue.empty()); @@ -98,17 +100,17 @@ namespace spot h.add_new_state(s0, CYAN); push(st_blue, s0, bddfalse, bddfalse); if (dfs_blue()) - return new se05_result(*this, options()); + return std::make_shared(t, options()); } else { h.pop_notify(st_red.front().s); pop(st_red); if (!st_red.empty() && dfs_red()) - return new se05_result(*this, options()); + return std::make_shared(t, options()); else if (dfs_blue()) - return new se05_result(*this, options()); + return std::make_shared(t, options()); } return 0; } @@ -330,27 +332,27 @@ namespace spot public acss_statistics { public: - result_from_stack(se05_search& ms) - : emptiness_check_result(ms.automaton()), ms_(ms) + result_from_stack(const std::shared_ptr& ms) + : emptiness_check_result(ms->automaton()), ms_(ms) { } - virtual tgba_run* accepting_run() + virtual tgba_run_ptr accepting_run() { - assert(!ms_.st_blue.empty()); - assert(!ms_.st_red.empty()); + assert(!ms_->st_blue.empty()); + assert(!ms_->st_red.empty()); - tgba_run* run = new tgba_run; + auto run = std::make_shared(); typename stack_type::const_reverse_iterator i, j, end; tgba_run::steps* l; - const state* target = ms_.st_red.front().s; + const state* target = ms_->st_red.front().s; l = &run->prefix; - i = ms_.st_blue.rbegin(); - end = ms_.st_blue.rend(); --end; + i = ms_->st_blue.rbegin(); + end = ms_->st_blue.rend(); --end; j = i; ++j; for (; i != end; ++i, ++j) { @@ -364,12 +366,12 @@ namespace spot l = &run->cycle; assert(l == &run->cycle); - j = ms_.st_red.rbegin(); + j = ms_->st_red.rbegin(); tgba_run::step s = { i->s->clone(), j->label, j->acc }; l->push_back(s); i = j; ++j; - end = ms_.st_red.rend(); --end; + end = ms_->st_red.rend(); --end; for (; i != end; ++i, ++j) { tgba_run::step s = { i->s->clone(), j->label, j->acc }; @@ -384,7 +386,7 @@ namespace spot return 0; } private: - se05_search& ms_; + std::shared_ptr ms_; }; # define FROM_STACK "ar:from_stack" @@ -392,8 +394,9 @@ namespace spot class se05_result: public emptiness_check_result { public: - se05_result(se05_search& m, option_map o = option_map()) - : emptiness_check_result(m.automaton(), o), ms(m) + se05_result(const std::shared_ptr& m, + option_map o = option_map()) + : emptiness_check_result(m->automaton(), o), ms(m) { if (options()[FROM_STACK]) computer = new result_from_stack(ms); @@ -420,7 +423,7 @@ namespace spot delete computer; } - virtual tgba_run* accepting_run() + virtual tgba_run_ptr accepting_run() { return computer->accepting_run(); } @@ -432,7 +435,7 @@ namespace spot private: emptiness_check_result* computer; - se05_search& ms; + std::shared_ptr ms; }; }; @@ -675,19 +678,20 @@ namespace spot } // anonymous - emptiness_check* explicit_se05_search(const const_tgba_ptr& a, option_map o) + emptiness_check_ptr + explicit_se05_search(const const_tgba_ptr& a, option_map o) { - return new se05_search(a, 0, o); + return std::make_shared>(a, 0, o); } - emptiness_check* bit_state_hashing_se05_search(const const_tgba_ptr& a, - size_t size, - option_map o) + emptiness_check_ptr + bit_state_hashing_se05_search(const const_tgba_ptr& a, + size_t size, option_map o) { - return new se05_search(a, size, o); + return std::make_shared>(a, size, o); } - emptiness_check* + emptiness_check_ptr se05(const const_tgba_ptr& a, option_map o) { size_t size = o.get("bsh"); diff --git a/src/tgbaalgos/se05.hh b/src/tgbaalgos/se05.hh index d50a9d856..a2230aca1 100644 --- a/src/tgbaalgos/se05.hh +++ b/src/tgbaalgos/se05.hh @@ -26,11 +26,10 @@ # include # include "misc/optionmap.hh" # include "tgba/fwd.hh" +# include "emptiness.hh" namespace spot { - class emptiness_check; - /// \addtogroup emptiness_check_algorithms /// @{ @@ -102,7 +101,7 @@ namespace spot /// /// \sa spot::explicit_magic_search /// - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr explicit_se05_search(const const_tgba_ptr& a, option_map o = option_map()); /// \brief Returns an emptiness checker on the spot::tgba automaton \a a. @@ -132,7 +131,7 @@ namespace spot /// /// \sa spot::explicit_se05_search /// - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr bit_state_hashing_se05_search(const const_tgba_ptr& a, size_t size, option_map o = option_map()); @@ -143,7 +142,7 @@ namespace spot /// bit_state_hashing_se05_search() according to the \c "bsh" option /// in the \c option_map. If \c "bsh" is set and non null, its value /// is used as the size of the hash map. - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr se05(const const_tgba_ptr& a, option_map o); /// @} diff --git a/src/tgbaalgos/tau03.cc b/src/tgbaalgos/tau03.cc index e18c5d5c6..7720a6376 100644 --- a/src/tgbaalgos/tau03.cc +++ b/src/tgbaalgos/tau03.cc @@ -83,18 +83,20 @@ namespace spot /// /// \return non null pointer iff the algorithm has found an /// accepting path. - virtual emptiness_check_result* check() + virtual emptiness_check_result_ptr check() { if (!st_blue.empty()) - return 0; + return nullptr; assert(st_red.empty()); const state* s0 = a_->get_init_state(); inc_states(); h.add_new_state(s0, BLUE); push(st_blue, s0, bddfalse, bddfalse); + auto t = std::static_pointer_cast + (this->emptiness_check::shared_from_this()); if (dfs_blue()) - return new ndfs_result, heap>(*this); - return 0; + return std::make_shared, heap>>(t); + return nullptr; } virtual std::ostream& print_stats(std::ostream &os) const @@ -374,9 +376,10 @@ namespace spot } // anonymous - emptiness_check* explicit_tau03_search(const const_tgba_ptr& a, option_map o) + emptiness_check_ptr + explicit_tau03_search(const const_tgba_ptr& a, option_map o) { - return new tau03_search(a, 0, o); + return std::make_shared>(a, 0, o); } } diff --git a/src/tgbaalgos/tau03.hh b/src/tgbaalgos/tau03.hh index cf99a6239..ce35f1faf 100644 --- a/src/tgbaalgos/tau03.hh +++ b/src/tgbaalgos/tau03.hh @@ -25,11 +25,10 @@ # include "misc/optionmap.hh" # include "tgba/fwd.hh" +# include "emptiness.hh" namespace spot { - class emptiness_check; - /// \addtogroup emptiness_check_algorithms /// @{ @@ -96,7 +95,7 @@ namespace spot } \endverbatim */ /// - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr explicit_tau03_search(const const_tgba_ptr& a, option_map o = option_map()); /// @} diff --git a/src/tgbaalgos/tau03opt.cc b/src/tgbaalgos/tau03opt.cc index 0b042e1ed..e490ebc44 100644 --- a/src/tgbaalgos/tau03opt.cc +++ b/src/tgbaalgos/tau03opt.cc @@ -108,18 +108,20 @@ namespace spot /// /// \return non null pointer iff the algorithm has found an /// accepting path. - virtual emptiness_check_result* check() + virtual emptiness_check_result_ptr check() { if (!st_blue.empty()) - return 0; + return nullptr; assert(st_red.empty()); const state* s0 = a_->get_init_state(); inc_states(); h.add_new_state(s0, CYAN, current_weight); push(st_blue, s0, bddfalse, bddfalse); + auto t = std::static_pointer_cast + (this->emptiness_check::shared_from_this()); if (dfs_blue()) - return new ndfs_result, heap>(*this); - return 0; + return std::make_shared, heap>>(t); + return nullptr; } virtual std::ostream& print_stats(std::ostream &os) const @@ -572,10 +574,12 @@ namespace spot } // anonymous - emptiness_check* explicit_tau03_opt_search(const const_tgba_ptr& a, - option_map o) + emptiness_check_ptr + explicit_tau03_opt_search(const const_tgba_ptr& a, option_map o) { - return new tau03_opt_search(a, 0, o); + return + std::make_shared>(a, + 0, o); } } diff --git a/src/tgbaalgos/tau03opt.hh b/src/tgbaalgos/tau03opt.hh index f05addaa4..10546a5f8 100644 --- a/src/tgbaalgos/tau03opt.hh +++ b/src/tgbaalgos/tau03opt.hh @@ -25,11 +25,10 @@ # include "misc/optionmap.hh" # include "tgba/fwd.hh" +# include "emptiness.hh" namespace spot { - class emptiness_check; - /// \addtogroup emptiness_check_algorithms /// @{ @@ -98,7 +97,7 @@ namespace spot /// the path stored in the blue stack. Such a vector is associated to each /// state of this stack. /// - SPOT_API emptiness_check* + SPOT_API emptiness_check_ptr explicit_tau03_opt_search(const const_tgba_ptr& a, option_map o = option_map()); diff --git a/src/tgbaalgos/word.cc b/src/tgbaalgos/word.cc index 50445b3a7..525c01d98 100644 --- a/src/tgbaalgos/word.cc +++ b/src/tgbaalgos/word.cc @@ -23,7 +23,7 @@ namespace spot { - tgba_word::tgba_word(const tgba_run* run) + tgba_word::tgba_word(const tgba_run_ptr run) { for (tgba_run::steps::const_iterator i = run->prefix.begin(); i != run->prefix.end(); ++i) diff --git a/src/tgbaalgos/word.hh b/src/tgbaalgos/word.hh index c5ab33860..7c9b4f9c6 100644 --- a/src/tgbaalgos/word.hh +++ b/src/tgbaalgos/word.hh @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2013 Laboratoire de Recherche et Développement de +// Copyright (C) 2013, 2014 Laboratoire de Recherche et Développement de // l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -29,7 +29,7 @@ namespace spot /// \brief An infinite word stored as a lasso. struct SPOT_API tgba_word { - tgba_word(const tgba_run* run); + tgba_word(const tgba_run_ptr run); void simplify(); std::ostream& print(std::ostream& os, const bdd_dict_ptr& d) const; diff --git a/src/tgbatest/checkpsl.cc b/src/tgbatest/checkpsl.cc index 7767ffd14..81a7d4e65 100644 --- a/src/tgbatest/checkpsl.cc +++ b/src/tgbatest/checkpsl.cc @@ -29,7 +29,6 @@ #include "tgbaalgos/ltl2taa.hh" #include "tgbaalgos/sccfilter.hh" #include "tgba/tgbaproduct.hh" -#include "tgbaalgos/gtec/gtec.hh" #include "tgbaalgos/dotty.hh" #include "tgbaalgos/dupexp.hh" @@ -76,14 +75,11 @@ main(int argc, char** argv) { auto apos = scc_filter(ltl_to_tgba_fm(fpos, d)); auto aneg = scc_filter(ltl_to_tgba_fm(fneg, d)); - auto ec = spot::couvreur99(spot::product(apos, aneg)); - auto res = ec->check(); - if (res) + if (!spot::product(apos, aneg)->is_empty()) { - std::cerr << "non-empty intersection between pos and neg (FM)\n"; - exit(2); + std::cerr << "non-empty intersection between pos and neg (FM)\n"; + exit(2); } - delete ec; // Run make_future_conditions_collector, without testing the output. auto fc = spot::make_future_conditions_collector(apos, true); @@ -93,28 +89,22 @@ main(int argc, char** argv) { auto apos = scc_filter(ltl_to_tgba_fm(fpos, d, true)); auto aneg = scc_filter(ltl_to_tgba_fm(fneg, d, true)); - auto ec = spot::couvreur99(spot::product(apos, aneg)); - auto res = ec->check(); - if (res) + if (!spot::product(apos, aneg)->is_empty()) { std::cerr << "non-empty intersection between pos and neg (FM -x)\n"; exit(2); } - delete ec; } if (fpos->is_ltl_formula()) { auto apos = scc_filter(spot::tgba_dupexp_dfs(ltl_to_taa(fpos, d))); auto aneg = scc_filter(spot::tgba_dupexp_dfs(ltl_to_taa(fneg, d))); - auto ec = spot::couvreur99(spot::product(apos, aneg)); - auto res = ec->check(); - if (res) + if (!spot::product(apos, aneg)->is_empty()) { std::cerr << "non-empty intersection between pos and neg (TAA)\n"; exit(2); - } - delete ec; + } } fpos->destroy(); fneg->destroy(); diff --git a/src/tgbatest/complementation.cc b/src/tgbatest/complementation.cc index cb5aa9a90..aa19c553c 100644 --- a/src/tgbatest/complementation.cc +++ b/src/tgbatest/complementation.cc @@ -274,8 +274,8 @@ int main(int argc, char* argv[]) nAf = spot::make_kv_complement(Af); nAnf = spot::make_kv_complement(Anf); } - spot::emptiness_check* ec = spot::couvreur99(spot::product(nAf, nAnf)); - spot::emptiness_check_result* res = ec->check(); + auto ec = spot::couvreur99(spot::product(nAf, nAnf)); + auto res = ec->check(); spot::tgba_statistics a_size = spot::stats_reachable(ec->automaton()); std::cout << "States: " << a_size.states << std::endl @@ -292,12 +292,8 @@ int main(int argc, char* argv[]) else std::cout << "OK"; std::cout << std::endl; - - delete res; - delete ec; nf1->destroy(); f1->destroy(); - } return return_value; diff --git a/src/tgbatest/emptchk.cc b/src/tgbatest/emptchk.cc index 1a1f70256..8176e68dc 100644 --- a/src/tgbatest/emptchk.cc +++ b/src/tgbatest/emptchk.cc @@ -122,7 +122,7 @@ main(int argc, char** argv) for (auto& algo: algos) { const char* err; - auto i = spot::emptiness_check_instantiator::construct(algo, &err); + auto i = spot::make_emptiness_check_instantiator(algo, &err); if (!i) { std::cerr << "Failed to parse `" << err << '\'' << std::endl; @@ -157,17 +157,14 @@ main(int argc, char** argv) int ce_found = 0; do { - auto res = ec->check(); - if (res) + if (auto res = ec->check()) { ++ce_found; std::cout << ce_found << " counterexample found\n"; - auto run = res->accepting_run(); - if (run) + if (auto run = res->accepting_run()) { auto ar = spot::tgba_run_to_tgba(a, run); spot::dotty_reachable(std::cout, ar, false); - delete run; } std::cout << '\n'; if (runs == 0) @@ -175,7 +172,6 @@ main(int argc, char** argv) std::cerr << "ERROR: Expected no counterexample.\n"; exit(1); } - delete res; } else { @@ -201,10 +197,7 @@ main(int argc, char** argv) std::cerr << "ERROR: expected a counterexample.\n"; exit(1); } - - delete ec; } - delete i; } f->destroy(); } diff --git a/src/tgbatest/ltl2tgba.cc b/src/tgbatest/ltl2tgba.cc index 46ca0c17c..6ccec85a4 100644 --- a/src/tgbatest/ltl2tgba.cc +++ b/src/tgbatest/ltl2tgba.cc @@ -354,7 +354,7 @@ checked_main(int argc, char** argv) int output = 0; int formula_index = 0; const char* echeck_algo = 0; - spot::emptiness_check_instantiator* echeck_inst = 0; + spot::emptiness_check_instantiator_ptr echeck_inst = 0; enum { NoneDup, BFS, DFS } dupexp = NoneDup; bool expect_counter_example = false; bool accepting_run = false; @@ -500,7 +500,7 @@ checked_main(int argc, char** argv) const char* err; echeck_inst = - spot::emptiness_check_instantiator::construct(echeck_algo, &err); + spot::make_emptiness_check_instantiator(echeck_algo, &err); if (!echeck_inst) { std::cerr << "Failed to parse argument of -e near `" @@ -518,7 +518,7 @@ checked_main(int argc, char** argv) const char* err; echeck_inst = - spot::emptiness_check_instantiator::construct(echeck_algo, &err); + spot::make_emptiness_check_instantiator(echeck_algo, &err); if (!echeck_inst) { std::cerr << "Failed to parse argument of -e near `" @@ -1713,13 +1713,13 @@ checked_main(int argc, char** argv) if (echeck_inst) { - spot::emptiness_check* ec = echeck_inst->instantiate(a); + auto ec = echeck_inst->instantiate(a); bool search_many = echeck_inst->options().get("repeated"); assert(ec); do { tm.start("running emptiness check"); - spot::emptiness_check_result* res = ec->check(); + auto res = ec->check(); tm.stop("running emptiness check"); if (paper_opt) @@ -1736,8 +1736,7 @@ checked_main(int argc, char** argv) std::cout << ec->automaton()->number_of_acceptance_conditions() << ", "; - const spot::ec_statistics* ecs = - dynamic_cast(ec); + auto ecs = ec->emptiness_check_statistics(); if (ecs) std::cout << std::right << std::setw(10) << ecs->states() << ", " @@ -1781,7 +1780,7 @@ checked_main(int argc, char** argv) { tm.start("computing accepting run"); - spot::tgba_run* run = res->accepting_run(); + auto run = res->accepting_run(); tm.stop("computing accepting run"); if (!run) @@ -1793,11 +1792,8 @@ checked_main(int argc, char** argv) if (opt_reduce) { tm.start("reducing accepting run"); - spot::tgba_run* redrun = - spot::reduce_run(res->automaton(), run); + run = spot::reduce_run(res->automaton(), run); tm.stop("reducing accepting run"); - delete run; - run = redrun; } if (accepting_run_replay) { @@ -1827,7 +1823,6 @@ checked_main(int argc, char** argv) } tm.stop("printing accepting run"); } - delete run; } } else @@ -1836,14 +1831,11 @@ checked_main(int argc, char** argv) << "(use -C to print it)" << std::endl; } } - delete res; } while (search_many); - delete ec; } if (f) f->destroy(); - delete echeck_inst; } else { diff --git a/src/tgbatest/randtgba.cc b/src/tgbatest/randtgba.cc index 29134e635..7150eb976 100644 --- a/src/tgbatest/randtgba.cc +++ b/src/tgbatest/randtgba.cc @@ -59,7 +59,7 @@ struct ec_algo { std::string name; - spot::emptiness_check_instantiator* inst; + spot::emptiness_check_instantiator_ptr inst; }; const char* default_algos[] = { @@ -84,12 +84,12 @@ const char* default_algos[] = { std::vector ec_algos; -spot::emptiness_check* +spot::emptiness_check_ptr cons_emptiness_check(int num, spot::const_tgba_ptr a, const spot::const_tgba_ptr& degen, unsigned int n_acc) { - spot::emptiness_check_instantiator* inst = ec_algos[num].inst; + auto inst = ec_algos[num].inst; if (n_acc < inst->min_acceptance_conditions() || n_acc > inst->max_acceptance_conditions()) a = degen; @@ -380,7 +380,7 @@ struct ar_stat } void - count(const spot::tgba_run* run) + count(const spot::const_tgba_run_ptr& run) { int p = run->prefix.size(); int c = run->cycle.size(); @@ -837,9 +837,8 @@ main(int argc, char** argv) { const char* err; ec_algos[i].inst = - spot::emptiness_check_instantiator::construct(ec_algos[i] - .name.c_str(), - &err); + spot::make_emptiness_check_instantiator(ec_algos[i].name.c_str(), + &err); if (ec_algos[i].inst == 0) { std::cerr << "Parse error after `" << err << '\'' << std::endl; @@ -939,9 +938,7 @@ main(int argc, char** argv) for (int i = 0; i < n_alg; ++i) { - spot::emptiness_check* ec; - spot::emptiness_check_result* res; - ec = cons_emptiness_check(i, a, degen, real_n_acc); + auto ec = cons_emptiness_check(i, a, degen, real_n_acc); if (!ec) continue; ++n_ec; @@ -952,17 +949,16 @@ main(int argc, char** argv) std::cout << algo << ": "; } tm_ec.start(algo); + spot::emptiness_check_result_ptr res; for (int count = opt_R;;) { res = ec->check(); if (count-- <= 0) break; - delete res; - delete ec; ec = cons_emptiness_check(i, a, degen, real_n_acc); } tm_ec.stop(algo); - const spot::unsigned_statistics* ecs = ec->statistics(); + auto ecs = ec->statistics(); if (opt_z && res) { // Notice that ratios are computed w.r.t. the @@ -1001,7 +997,7 @@ main(int argc, char** argv) ++n_non_empty; if (opt_replay) { - spot::tgba_run* run; + spot::tgba_run_ptr run; bool done = false; tm_ar.start(algo); for (int count = opt_R;;) @@ -1030,7 +1026,6 @@ main(int argc, char** argv) if (count-- <= 0 || !run) break; - delete run; } if (!run) { @@ -1065,7 +1060,7 @@ main(int argc, char** argv) if (opt_reduce) { - spot::tgba_run* redrun = + auto redrun = spot::reduce_run(res->automaton(), run); if (!spot::replay_tgba_run(s, res @@ -1093,14 +1088,11 @@ main(int argc, char** argv) << redrun->cycle.size() << ']'; } - delete redrun; } - delete run; } } if (!opt_paper) std::cout << std::endl; - delete res; } else { @@ -1122,7 +1114,6 @@ main(int argc, char** argv) if (opt_Z && !opt_paper) ec->print_stats(std::cout); - delete ec; } assert(n_empty + n_non_empty + n_maybe_empty == n_ec); @@ -1310,10 +1301,6 @@ main(int argc, char** argv) delete formula_file; } - if (opt_ec) - for (unsigned i = 0; i < ec_algos.size(); ++i) - delete ec_algos[i].inst; - delete ap; delete apf; return exit_code; diff --git a/wrap/python/ajax/spot.in b/wrap/python/ajax/spot.in index 6d77fa918..6877b47c6 100755 --- a/wrap/python/ajax/spot.in +++ b/wrap/python/ajax/spot.in @@ -102,7 +102,6 @@ if not script: httpd.serve_forever() import cgi -import cgitb; cgitb.enable() import signal import time import os.path @@ -120,6 +119,9 @@ sys.stdout = os.fdopen(sys.stdout.fileno(), "wb", 0) # even errors from subprocesses get printed). os.dup2(sys.stdout.fileno(), sys.stderr.fileno()) +import cgitb +sys.excepthook = cgitb.Hook(file=sys.stderr) + # Create the temporary cache directory os.mkdir(tmpdir, 493) # See comment above about 0o755 or 0755. @@ -533,7 +535,7 @@ elif translator == 'ta': refined_rules = False if form.getfirst('ta', '') == 'lc': refined_rules = True - automaton = spot.ltl_to_taa(f, dict, refined_rules) + automaton = spot.tgba_dupexp_dfs(spot.ltl_to_taa(f, dict, refined_rules)) elif translator == 'l3': l3out = '-T' l3opt = { '-l', '-P', '-A', '-c', '-C', '-o', '-p' } @@ -770,7 +772,7 @@ if output_type == 'r': err = "" opt = (form.getfirst('ec', 'Cou99') + "(" + form.getfirst('eo', '') + ")") - eci, err = spot.emptiness_check_instantiator.construct(opt) + eci, err = spot.make_emptiness_check_instantiator(opt) if not eci: unbufprint('
Cannot parse "' + opt @@ -824,8 +826,4 @@ if output_type == 'r': del ec_run del ec_res unbufprint('
') - del ec - del ec_a - degen = 0 - automaton = 0 finish() diff --git a/wrap/python/spot.i b/wrap/python/spot.i index a4483cb52..ed3c4eb42 100644 --- a/wrap/python/spot.i +++ b/wrap/python/spot.i @@ -36,7 +36,6 @@ // sed 's/.*<\(.*\)>.*/%shared_ptr(spot::\1)/g' %shared_ptr(spot::bdd_dict) %shared_ptr(spot::dstar_aut) -%shared_ptr(spot::dstar_aut) %shared_ptr(spot::future_conditions_collector) %shared_ptr(spot::kripke) %shared_ptr(spot::saba) @@ -56,6 +55,10 @@ %shared_ptr(spot::tgba_sgba_proxy) %shared_ptr(spot::tgta) %shared_ptr(spot::tgta_explicit) +%shared_ptr(spot::tgba_run) +%shared_ptr(spot::emptiness_check) +%shared_ptr(spot::emptiness_check_result) +%shared_ptr(spot::emptiness_check_instantiator) namespace std { %template(liststr) list; @@ -203,19 +206,8 @@ using namespace spot; %include "ltlvisit/simplify.hh" %include "ltlvisit/tostring.hh" %include "ltlvisit/tunabbrev.hh" -%include "ltlvisit/apcollect.hh" %include "ltlvisit/lbt.hh" -%feature("new") spot::emptiness_check::check; -%feature("new") spot::emptiness_check_instantiator::construct; -%feature("new") spot::emptiness_check_instantiator::instanciate; -%feature("new") spot::emptiness_check_result::accepting_run; -%feature("new") spot::explicit_magic_search; -%feature("new") spot::explicit_se05_search; -%feature("new") spot::tgba::get_init_state; -%feature("new") spot::tgba::succ_iter; -%feature("new") spot::tgba_succ_iterator::current_state; - // Help SWIG with namespace lookups. #define ltl spot::ltl %include "tgba/bddprint.hh" @@ -232,6 +224,9 @@ namespace spot { }; } +// Should come after the definition of tgba_digraph +%include "ltlvisit/apcollect.hh" + %include "tgbaalgos/degen.hh" %include "tgbaalgos/dottydec.hh" %include "tgbaalgos/dotty.hh"