Commit ebdb198b authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz

hierarchy: expose mp_class to python

* bin/common_output.cc: Move some of the printing code...
* spot/tl/hierarchy.cc, spot/tl/hierarchy.hh: ... here, as new
  variants of mp_class...
* python/spot/impl.i: ... that we can now call from Python.
* python/ajax/spotcgi.in: Use those to simplify and extend
the code printing class membership.
parent a0891fde
// -*- coding: utf-8 -*- // -*- 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). // Développement de l'Epita (LRDE).
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
...@@ -172,92 +172,10 @@ namespace ...@@ -172,92 +172,10 @@ namespace
virtual void virtual void
print(std::ostream& os, const char* opt) const override print(std::ostream& os, const char* opt) const override
{ {
bool verbose = false;
bool wide = false;
if (*opt == '[') if (*opt == '[')
do os << spot::mp_class(val_, opt + 1);
switch (*++opt) else
{ os << val_;
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;
}
}
} }
}; };
......
...@@ -505,24 +505,20 @@ if output_type == 'f': ...@@ -505,24 +505,20 @@ if output_type == 'f':
for p in spot.list_formula_props(f): for p in spot.list_formula_props(f):
unbufprint('<li>%s</li>\n' % p) unbufprint('<li>%s</li>\n' % p)
# Attempt to refine the hierarchy class using WDBA minimization mpc = spot.mp_class(f, 'w')
if not f.is_syntactic_safety() or not f.is_syntactic_guarantee(): if 'S' in mpc:
dict = spot.bdd_dict() unbufprint('<li>safety</li>')
automaton = spot.ltl_to_tgba_fm(f, dict, False, True) if 'G' in mpc:
minimized = spot.minimize_obligation(automaton, f) unbufprint('<li>guarantee</li>')
if minimized != automaton: if 'O' in mpc:
g = spot.is_terminal_automaton(minimized, None, True) unbufprint('<li>obligation</li>')
s = spot.is_safety_automaton(minimized) if 'R' in mpc:
if s and not f.is_syntactic_safety(): unbufprint('<li>recurrence</li>')
unbufprint('<li>pathologic safety</li>') if 'P' in mpc:
if g and not f.is_syntactic_guarantee(): unbufprint('<li>persistence</li>')
unbufprint('<li>pathologic guarantee</li>') if 'T' == mpc:
if not f.is_syntactic_obligation(): unbufprint('<li>not a persistence nor a recurrence</li>')
unbufprint('<li>obligation (although not syntactically)</li>')
else:
unbufprint('<li>not an obligation</li>')
minimized = 0
automaton = 0
if not f.is_syntactic_stutter_invariant(): if not f.is_syntactic_stutter_invariant():
if spot.is_stutter_invariant(f): if spot.is_stutter_invariant(f):
unbufprint('<li>stutter invariant</li>') unbufprint('<li>stutter invariant</li>')
......
// -*- coding: utf-8 -*- // -*- 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). // Laboratoire de Recherche et Développement de l'Epita (LRDE).
// Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique // Copyright (C) 2003, 2004, 2005, 2006 Laboratoire d'Informatique
// de Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC), // de Paris 6 (LIP6), département Systèmes Répartis Coopératifs (SRC),
...@@ -103,6 +103,7 @@ ...@@ -103,6 +103,7 @@
#include <spot/tl/randomltl.hh> #include <spot/tl/randomltl.hh>
#include <spot/tl/length.hh> #include <spot/tl/length.hh>
#include <spot/tl/ltlf.hh> #include <spot/tl/ltlf.hh>
#include <spot/tl/hierarchy.hh>
#include <spot/tl/remove_x.hh> #include <spot/tl/remove_x.hh>
#include <spot/tl/relabel.hh> #include <spot/tl/relabel.hh>
...@@ -448,6 +449,7 @@ namespace std { ...@@ -448,6 +449,7 @@ namespace std {
%include <spot/tl/randomltl.hh> %include <spot/tl/randomltl.hh>
%include <spot/tl/length.hh> %include <spot/tl/length.hh>
%include <spot/tl/ltlf.hh> %include <spot/tl/ltlf.hh>
%include <spot/tl/hierarchy.hh>
%include <spot/tl/remove_x.hh> %include <spot/tl/remove_x.hh>
%include <spot/tl/relabel.hh> %include <spot/tl/relabel.hh>
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <sstream>
#include <spot/tl/hierarchy.hh> #include <spot/tl/hierarchy.hh>
#include <spot/twaalgos/isdet.hh> #include <spot/twaalgos/isdet.hh>
#include <spot/twaalgos/ltl2tgba_fm.hh> #include <spot/twaalgos/ltl2tgba_fm.hh>
...@@ -85,4 +86,108 @@ namespace spot ...@@ -85,4 +86,108 @@ namespace spot
return 'P'; return 'P';
return 'T'; 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();
}
} }
...@@ -37,4 +37,34 @@ namespace spot ...@@ -37,4 +37,34 @@ namespace spot
/// - 'T' (top) properties that are not persistence or recurrence /// - 'T' (top) properties that are not persistence or recurrence
/// properties /// properties
SPOT_API char mp_class(formula f); 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);
} }
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment