diff --git a/bin/common_output.cc b/bin/common_output.cc index 0c0d8625784b04f82297dee7ea7cbac3a96f93ba..2a6a920607ae447c2547d99540e5ac55b1e1f132 100644 --- a/bin/common_output.cc +++ b/bin/common_output.cc @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2012, 2013, 2014, 2015, 2016 Laboratoire de Recherche et +// Copyright (C) 2012, 2013, 2014, 2015, 2016, 2017 Laboratoire de Recherche et // Développement de l'Epita (LRDE). // // This file is part of Spot, a model checking library. @@ -172,92 +172,10 @@ namespace virtual void print(std::ostream& os, const char* opt) const override { - bool verbose = false; - bool wide = false; if (*opt == '[') - do - switch (*++opt) - { - case 'v': - verbose = true; - break; - case 'w': - wide = true; - break; - case ' ': - case '\t': - case '\n': - case ',': - case ']': - break; - } - while (*opt != ']'); - - std::string c(1, val_); - if (wide) - { - switch (val_) - { - case 'B': - c = "GSOPRT"; - break; - case 'G': - c = "GOPRT"; - break; - case 'S': - c = "SOPRT"; - break; - case 'O': - c = "OPRT"; - break; - case 'P': - c = "PT"; - break; - case 'R': - c = "RT"; - break; - case 'T': - break; - } - } - if (!verbose) - { - os << c; - return; - } - - bool first = true; - for (char ch: c) - { - if (first) - first = false; - else - os << ' '; - switch (ch) - { - case 'B': - os << "guarantee safety"; - break; - case 'G': - os << "guarantee"; - break; - case 'S': - os << "safety"; - break; - case 'O': - os << "obligation"; - break; - case 'P': - os << "persistence"; - break; - case 'R': - os << "recurrence"; - break; - case 'T': - os << "reactivity"; - break; - } - } + os << spot::mp_class(val_, opt + 1); + else + os << val_; } }; diff --git a/python/ajax/spotcgi.in b/python/ajax/spotcgi.in index 474d10edf64386c7fe5cc7767ab198cffa06a693..d0f9402085fb8fa8111b010774bd0256ffdd942a 100755 --- a/python/ajax/spotcgi.in +++ b/python/ajax/spotcgi.in @@ -505,24 +505,20 @@ if output_type == 'f': for p in spot.list_formula_props(f): unbufprint('
  • %s
  • \n' % p) - # Attempt to refine the hierarchy class using WDBA minimization - if not f.is_syntactic_safety() or not f.is_syntactic_guarantee(): - dict = spot.bdd_dict() - automaton = spot.ltl_to_tgba_fm(f, dict, False, True) - minimized = spot.minimize_obligation(automaton, f) - if minimized != automaton: - g = spot.is_terminal_automaton(minimized, None, True) - s = spot.is_safety_automaton(minimized) - if s and not f.is_syntactic_safety(): - unbufprint('
  • pathologic safety
  • ') - if g and not f.is_syntactic_guarantee(): - unbufprint('
  • pathologic guarantee
  • ') - if not f.is_syntactic_obligation(): - unbufprint('
  • obligation (although not syntactically)
  • ') - else: - unbufprint('
  • not an obligation
  • ') - minimized = 0 - automaton = 0 + mpc = spot.mp_class(f, 'w') + if 'S' in mpc: + unbufprint('
  • safety
  • ') + if 'G' in mpc: + unbufprint('
  • guarantee
  • ') + if 'O' in mpc: + unbufprint('
  • obligation
  • ') + if 'R' in mpc: + unbufprint('
  • recurrence
  • ') + if 'P' in mpc: + unbufprint('
  • persistence
  • ') + if 'T' == mpc: + unbufprint('
  • not a persistence nor a recurrence
  • ') + if not f.is_syntactic_stutter_invariant(): if spot.is_stutter_invariant(f): unbufprint('
  • stutter invariant
  • ') diff --git a/python/spot/impl.i b/python/spot/impl.i index cff9ca1c9e347537281cf2d11e3d432275da441b..8dfefa14ef1bd4ae825458c15b3b8555e470dd87 100644 --- a/python/spot/impl.i +++ b/python/spot/impl.i @@ -1,5 +1,5 @@ // -*- coding: utf-8 -*- -// Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 +// Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 // Laboratoire de Recherche et Développement de l'Epita (LRDE). // Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique // de Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC), @@ -103,6 +103,7 @@ #include #include #include +#include #include #include @@ -448,6 +449,7 @@ namespace std { %include %include %include +%include %include %include diff --git a/spot/tl/hierarchy.cc b/spot/tl/hierarchy.cc index 53c5531e3121041913df1d279f559dc94051f7fc..e7967209f82664278396d1993ae48140f2709414 100644 --- a/spot/tl/hierarchy.cc +++ b/spot/tl/hierarchy.cc @@ -17,6 +17,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#include #include #include #include @@ -85,4 +86,108 @@ namespace spot return 'P'; return 'T'; } + + std::string mp_class(formula f, const char* opt) + { + return mp_class(mp_class(f), opt); + } + + std::string mp_class(char mpc, const char* opt) + { + bool verbose = false; + bool wide = false; + if (opt) + for (;;) + switch (int o = *opt++) + { + case 'v': + verbose = true; + break; + case 'w': + wide = true; + break; + case ' ': + case '\t': + case '\n': + case ',': + break; + case '\0': + case ']': + goto break2; + default: + { + std::ostringstream err; + err << "unknown option '" << o << "' for mp_class()"; + throw std::runtime_error(err.str()); + } + } + break2: + std::string c(1, mpc); + if (wide) + { + switch (mpc) + { + case 'B': + c = "GSOPRT"; + break; + case 'G': + c = "GOPRT"; + break; + case 'S': + c = "SOPRT"; + break; + case 'O': + c = "OPRT"; + break; + case 'P': + c = "PT"; + break; + case 'R': + c = "RT"; + break; + case 'T': + break; + default: + throw std::runtime_error("mp_class() called with unknown class"); + } + } + if (!verbose) + return c; + + std::ostringstream os; + bool first = true; + for (char ch: c) + { + if (first) + first = false; + else + os << ' '; + switch (ch) + { + case 'B': + os << "guarantee safety"; + break; + case 'G': + os << "guarantee"; + break; + case 'S': + os << "safety"; + break; + case 'O': + os << "obligation"; + break; + case 'P': + os << "persistence"; + break; + case 'R': + os << "recurrence"; + break; + case 'T': + os << "reactivity"; + break; + } + } + return os.str(); + } + } diff --git a/spot/tl/hierarchy.hh b/spot/tl/hierarchy.hh index 150ac91f878962d03557a6d3196efaeded213950..88def1831b9e846985a8f4caab9a0f5dce6eb79d 100644 --- a/spot/tl/hierarchy.hh +++ b/spot/tl/hierarchy.hh @@ -37,4 +37,34 @@ namespace spot /// - 'T' (top) properties that are not persistence or recurrence /// properties SPOT_API char mp_class(formula f); + + + /// \brief Return the class of \a f in the temporal hierarchy of Manna + /// and Pnueli (PODC'90). + /// + /// The \a opt parameter should be a string specifying options + /// for expressing the class. If \a opt is empty, the + /// result is one character among B, G, S, O, P, R, T, specifying + /// the most precise class to which the formula belongs. + /// If \a opt contains 'w', then the string contains all the + /// characters corresponding to the classes that contain \a f. + /// If \a opt contains 'v', then the characters are replaced + /// by the name of each class. Space and commas are ignored. + /// Any ']' ends the processing of the options. + SPOT_API std::string mp_class(formula f, const char* opt); + + /// \brief Expand a class in the temporal hierarchy of Manna + /// and Pnueli (PODC'90). + /// + /// \a mpc should be a character among B, G, S, O, P, R, T + /// specifying a class in the hierarchy. + /// + /// The \a opt parameter should be a string specifying options for + /// expressing the class. If \a opt is empty, the result is \a mpc. + /// If \a opt contains 'w', then the string contains all the + /// characters corresponding to the super-classes of \a mpc. If \a + /// opt contains 'v', then the characters are replaced by the name + /// of each class. Space and commas are ignored. Any ']' ends the + /// processing of the options. + SPOT_API std::string mp_class(char mpc, const char* opt); }