kill the ltl namespace
* NEWS: Mention it. * bench/stutter/stutter_invariance_formulas.cc, bench/stutter/stutter_invariance_randomgraph.cc, doc/mainpage.dox, doc/org/tut01.org, doc/org/tut02.org, doc/org/tut10.org, doc/tl/tl.tex, iface/ltsmin/ltsmin.cc, iface/ltsmin/ltsmin.hh, iface/ltsmin/modelcheck.cc, src/bin/autfilt.cc, src/bin/common_aoutput.cc, src/bin/common_aoutput.hh, src/bin/common_finput.cc, src/bin/common_finput.hh, src/bin/common_output.cc, src/bin/common_output.hh, src/bin/common_r.hh, src/bin/common_trans.cc, src/bin/common_trans.hh, src/bin/dstar2tgba.cc, src/bin/genltl.cc, src/bin/ltl2tgba.cc, src/bin/ltl2tgta.cc, src/bin/ltlcross.cc, src/bin/ltldo.cc, src/bin/ltlfilt.cc, src/bin/ltlgrind.cc, src/bin/randaut.cc, src/bin/randltl.cc, src/kripke/kripkeexplicit.cc, src/kripke/kripkeexplicit.hh, src/kripkeparse/kripkeparse.yy, src/kripkeparse/public.hh, src/ltlparse/fmterror.cc, src/ltlparse/ltlparse.yy, src/ltlparse/ltlscan.ll, src/ltlparse/parsedecl.hh, src/ltlparse/public.hh, src/parseaut/parseaut.yy, src/parseaut/public.hh, src/tests/checkpsl.cc, src/tests/checkta.cc, src/tests/complementation.cc, src/tests/consterm.cc, src/tests/emptchk.cc, src/tests/equalsf.cc, src/tests/ikwiad.cc, src/tests/kind.cc, src/tests/length.cc, src/tests/ltlprod.cc, src/tests/ltlrel.cc, src/tests/parse.test, src/tests/parse_print_test.cc, src/tests/randtgba.cc, src/tests/readltl.cc, src/tests/reduc.cc, src/tests/syntimpl.cc, src/tests/taatgba.cc, src/tests/tostring.cc, src/tests/tostring.test, src/tl/apcollect.cc, src/tl/apcollect.hh, src/tl/contain.cc, src/tl/contain.hh, src/tl/declenv.cc, src/tl/declenv.hh, src/tl/defaultenv.cc, src/tl/defaultenv.hh, src/tl/dot.cc, src/tl/dot.hh, src/tl/environment.hh, src/tl/exclusive.cc, src/tl/exclusive.hh, src/tl/formula.cc, src/tl/formula.hh, src/tl/length.cc, src/tl/length.hh, src/tl/mark.cc, src/tl/mark.hh, src/tl/mutation.cc, src/tl/mutation.hh, src/tl/nenoform.cc, src/tl/nenoform.hh, src/tl/print.cc, src/tl/print.hh, src/tl/randomltl.cc, src/tl/randomltl.hh, src/tl/relabel.cc, src/tl/relabel.hh, src/tl/remove_x.cc, src/tl/remove_x.hh, src/tl/simpfg.cc, src/tl/simpfg.hh, src/tl/simplify.cc, src/tl/simplify.hh, src/tl/snf.cc, src/tl/snf.hh, src/tl/unabbrev.cc, src/tl/unabbrev.hh, src/twa/bdddict.cc, src/twa/bdddict.hh, src/twa/bddprint.cc, src/twa/formula2bdd.cc, src/twa/formula2bdd.hh, src/twa/taatgba.cc, src/twa/taatgba.hh, src/twa/twa.hh, src/twa/twagraph.cc, src/twa/twagraph.hh, src/twaalgos/compsusp.cc, src/twaalgos/compsusp.hh, src/twaalgos/ltl2taa.cc, src/twaalgos/ltl2taa.hh, src/twaalgos/ltl2tgba_fm.cc, src/twaalgos/ltl2tgba_fm.hh, src/twaalgos/minimize.cc, src/twaalgos/minimize.hh, src/twaalgos/neverclaim.cc, src/twaalgos/postproc.cc, src/twaalgos/postproc.hh, src/twaalgos/powerset.cc, src/twaalgos/powerset.hh, src/twaalgos/randomgraph.cc, src/twaalgos/randomgraph.hh, src/twaalgos/relabel.cc, src/twaalgos/relabel.hh, src/twaalgos/remprop.cc, src/twaalgos/remprop.hh, src/twaalgos/stats.cc, src/twaalgos/stats.hh, src/twaalgos/stutter.cc, src/twaalgos/stutter.hh, src/twaalgos/translate.cc, src/twaalgos/translate.hh, wrap/python/spot_impl.i: Remove the ltl namespace.
This commit is contained in:
parent
6ded5e75c4
commit
cb39210166
137 changed files with 10771 additions and 10919 deletions
17
NEWS
17
NEWS
|
|
@ -28,9 +28,9 @@ New in spot 1.99.3a (not yet released)
|
|||
* The class hierarchy for temporal formulas has been entirely
|
||||
rewritten. This change is actually quite massive (~13200 lines
|
||||
removed, ~8200 lines added), and brings some nice benefits:
|
||||
- LTL/PSL formulas are now represented by lightweight ltl::formula
|
||||
objects (instead of ltl::formula* pointers) that perform
|
||||
reference counting automatically.
|
||||
- LTL/PSL formulas are now represented by lightweight formula
|
||||
objects (instead of pointers to children of an abstract formula
|
||||
class) that perform reference counting automatically.
|
||||
- There is no hierachy anymore: all operators are represented by a
|
||||
single type of node in the syntax tree, and an enumerator is
|
||||
used to distinguish between operators.
|
||||
|
|
@ -41,10 +41,13 @@ New in spot 1.99.3a (not yet released)
|
|||
more friendly, and several algorithms that spanned a few pages
|
||||
have been reduced to a few lines.
|
||||
|
||||
* The source directories ltlast/, ltlenv/, and ltlvisit/, have been
|
||||
merged into a single tl/ directory (for temporal logic). This is
|
||||
motivated by the fact that these formulas are not restricted to
|
||||
LTL, and by the fact that we no longuer use the "visitor" pattern.
|
||||
* Directories ltlast/, ltlenv/, and ltlvisit/, have been merged into
|
||||
a single tl/ directory (for temporal logic). This is motivated by
|
||||
the fact that these formulas are not restricted to LTL, and by the
|
||||
fact that we no longuer use the "visitor" pattern.
|
||||
|
||||
* For similar reasons, the spot::ltl namespace has been merged
|
||||
with the spot namespace.
|
||||
|
||||
New in spot 1.99.3 (2015-08-26)
|
||||
|
||||
|
|
|
|||
|
|
@ -62,12 +62,12 @@ namespace
|
|||
}
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula f, const char*, int)
|
||||
process_formula(spot::formula f, const char*, int)
|
||||
{
|
||||
spot::twa_graph_ptr a = trans.run(f);
|
||||
spot::twa_graph_ptr na = trans.run(spot::ltl::formula::Not(f));
|
||||
spot::ltl::atomic_prop_set* ap = spot::ltl::atomic_prop_collect(f);
|
||||
bdd apdict = spot::ltl::atomic_prop_collect_as_bdd(f, a);
|
||||
spot::twa_graph_ptr na = trans.run(spot::formula::Not(f));
|
||||
spot::atomic_prop_set* ap = spot::atomic_prop_collect(f);
|
||||
bdd apdict = spot::atomic_prop_collect_as_bdd(f, a);
|
||||
|
||||
std::cout << formula << ',' << ap->size() << ',';
|
||||
stats.print(a);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ main(int argc, char** argv)
|
|||
constexpr unsigned n = 10;
|
||||
|
||||
// random ap set
|
||||
auto ap = spot::ltl::create_atomic_prop_set(props_n);
|
||||
auto ap = spot::create_atomic_prop_set(props_n);
|
||||
// ap set as bdd
|
||||
bdd apdict = bddtrue;
|
||||
for (auto& i: ap)
|
||||
|
|
|
|||
|
|
@ -19,12 +19,12 @@
|
|||
///
|
||||
/// \section pointers Handy starting points
|
||||
///
|
||||
/// \li spot::ltl::formula Base class for an LTL or PSL formula.
|
||||
/// \li spot::ltl::parse_infix_psl Parsing a text string into a
|
||||
/// spot::ltl::formula.
|
||||
/// \li spot::formula Base class for an LTL or PSL formula.
|
||||
/// \li spot::parse_infix_psl Parsing a text string into a
|
||||
/// spot::formula.
|
||||
/// \li spot::twa Base class for Transition-based
|
||||
/// ω-Automata.
|
||||
/// \li spot::translator Convert a spot::ltl::formula into a
|
||||
/// \li spot::translator Convert a spot::formula into a
|
||||
/// spot::tgba.
|
||||
/// \li spot::kripke Base class for Kripke structures.
|
||||
/// \li spot::twa_product On-the-fly product of two spot::twa.
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ exceptions.
|
|||
|
||||
int main()
|
||||
{
|
||||
print_latex_psl(std::cout, spot::ltl::parse_formula("[]<>p0 || <>[]p1")) << '\n';
|
||||
spot::ltl::formula f = spot::ltl::parse_formula("& & G p0 p1 p2");
|
||||
print_latex_psl(std::cout, spot::parse_formula("[]<>p0 || <>[]p1")) << '\n';
|
||||
spot::formula f = spot::parse_formula("& & G p0 p1 p2");
|
||||
print_lbt_ltl(std::cout, f) << '\n';
|
||||
print_spin_ltl(std::cout, f, true) << '\n';
|
||||
return 0;
|
||||
|
|
@ -110,9 +110,9 @@ Here is how to call the infix parser explicitly,:
|
|||
int main()
|
||||
{
|
||||
std::string input = "[]<>p0 || <>[]p1";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_infix_psl(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
return 1;
|
||||
print_latex_psl(std::cout, f) << '\n';
|
||||
return 0;
|
||||
|
|
@ -152,11 +152,11 @@ with the "fixed" formula if you wish. Here is an example:
|
|||
int main()
|
||||
{
|
||||
std::string input = "(a U b))";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_infix_psl(input, pel);
|
||||
// Use std::cout instead of std::cerr because we can only
|
||||
// show the output of std::cout in this documentation.
|
||||
(void) spot::ltl::format_parse_errors(std::cout, input, pel);
|
||||
(void) spot::format_parse_errors(std::cout, input, pel);
|
||||
if (f == nullptr)
|
||||
return 1;
|
||||
std::cout << "Parsed formula: ";
|
||||
|
|
@ -194,9 +194,9 @@ of =parse_infix_psl()=.
|
|||
int main()
|
||||
{
|
||||
std::string input = "& & G p0 p1 p2";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_prefix_ltl(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_prefix_ltl(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
return 1;
|
||||
print_lbt_ltl(std::cout, f) << '\n';
|
||||
print_spin_ltl(std::cout, f, true) << '\n';
|
||||
|
|
@ -236,9 +236,9 @@ For instance, let's see what happens if a PSL formulas is passed to
|
|||
int main()
|
||||
{
|
||||
std::string input = "{a*;b}<>->(a U (b & GF c))";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_infix_psl(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
return 1;
|
||||
print_spin_ltl(std::cout, f) << '\n';
|
||||
return 0;
|
||||
|
|
@ -266,9 +266,9 @@ The first is to simply diagnose non-LTL formulas.
|
|||
int main()
|
||||
{
|
||||
std::string input = "{a*;b}<>->(a U (b & GF c))";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_infix_psl(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
return 1;
|
||||
if (!f.is_ltl_formula())
|
||||
{
|
||||
|
|
@ -296,13 +296,13 @@ prepared to reject the formula any way. In our example, we are lucky
|
|||
int main()
|
||||
{
|
||||
std::string input = "{a*;b}<>->(a U (b & GF c))";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_infix_psl(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
return 1;
|
||||
if (!f.is_ltl_formula())
|
||||
{
|
||||
spot::ltl::ltl_simplifier simp;
|
||||
spot::ltl_simplifier simp;
|
||||
f = simp.simplify(f);
|
||||
}
|
||||
if (!f.is_ltl_formula())
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ print(g.to_str('spin', True))
|
|||
|
||||
* C++
|
||||
|
||||
The =spot::ltl::relabeling_map= is just a =std::map= with a custom
|
||||
The =spot::relabeling_map= is just a =std::map= with a custom
|
||||
destructor.
|
||||
|
||||
#+BEGIN_SRC C++ :results verbatim :exports both
|
||||
|
|
@ -87,12 +87,12 @@ destructor.
|
|||
int main()
|
||||
{
|
||||
std::string input = "\"Proc@Here\" U (\"var > 10\" | \"var < 4\")";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_infix_psl(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
return 1;
|
||||
spot::ltl::relabeling_map m;
|
||||
f = spot::ltl::relabel(f, spot::ltl::Pnn, &m);
|
||||
spot::relabeling_map m;
|
||||
f = spot::relabel(f, spot::Pnn, &m);
|
||||
for (auto& i: m)
|
||||
{
|
||||
std::cout << "#define ";
|
||||
|
|
@ -115,8 +115,8 @@ destructor.
|
|||
|
||||
** Two ways to name atomic propositions
|
||||
|
||||
Instead of =--relabel=pnn= (or =spot.Pnn=, or =spot::ltl::Pnn=), you can
|
||||
actually use =--relabel=abc= (or =spot.Abc=, or =spot::ltl::Abc=) to have
|
||||
Instead of =--relabel=pnn= (or =spot.Pnn=, or =spot::Pnn=), you can
|
||||
actually use =--relabel=abc= (or =spot.Abc=, or =spot::Abc=) to have
|
||||
the atomic propositions named =a=, =b=, =c=, etc.
|
||||
|
||||
** Relabeling Boolean sub-expressions
|
||||
|
|
|
|||
|
|
@ -137,9 +137,9 @@ never claim is done via the =print_never_claim= function.
|
|||
int main()
|
||||
{
|
||||
std::string input = "[]<>p0 || <>[]p1";
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = spot::parse_infix_psl(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
return 1;
|
||||
spot::translator trans;
|
||||
trans.set_type(spot::postprocessor::BA);
|
||||
|
|
|
|||
|
|
@ -1001,7 +1001,7 @@ both right-associative, other have only $\IMPLIES$ as right-associative.
|
|||
|
||||
When Spot builds a formula (represented by an AST with shared
|
||||
subtrees) it computes a set of properties for each node. These
|
||||
properties can be queried from any \texttt{spot::ltl::formula}
|
||||
properties can be queried from any \texttt{spot::formula}
|
||||
instance using the following methods:
|
||||
|
||||
\noindent
|
||||
|
|
|
|||
|
|
@ -323,10 +323,10 @@ namespace spot
|
|||
|
||||
|
||||
int
|
||||
convert_aps(const ltl::atomic_prop_set* aps,
|
||||
convert_aps(const atomic_prop_set* aps,
|
||||
const spins_interface* d,
|
||||
bdd_dict_ptr dict,
|
||||
ltl::formula dead,
|
||||
formula dead,
|
||||
prop_set& out)
|
||||
{
|
||||
int errors = 0;
|
||||
|
|
@ -353,7 +353,7 @@ namespace spot
|
|||
enum_map[i].emplace(d->get_type_value_name(i, j), j);
|
||||
}
|
||||
|
||||
for (ltl::atomic_prop_set::const_iterator ap = aps->begin();
|
||||
for (atomic_prop_set::const_iterator ap = aps->begin();
|
||||
ap != aps->end(); ++ap)
|
||||
{
|
||||
if (*ap == dead)
|
||||
|
|
@ -602,7 +602,7 @@ namespace spot
|
|||
public:
|
||||
|
||||
spins_kripke(const spins_interface* d, const bdd_dict_ptr& dict,
|
||||
const spot::prop_set* ps, ltl::formula dead,
|
||||
const spot::prop_set* ps, formula dead,
|
||||
int compress)
|
||||
: kripke(dict),
|
||||
d_(d),
|
||||
|
|
@ -1016,8 +1016,8 @@ namespace spot
|
|||
|
||||
kripke_ptr
|
||||
load_ltsmin(const std::string& file_arg, const bdd_dict_ptr& dict,
|
||||
const ltl::atomic_prop_set* to_observe,
|
||||
const ltl::formula dead, int compress, bool verbose)
|
||||
const atomic_prop_set* to_observe,
|
||||
const formula dead, int compress, bool verbose)
|
||||
{
|
||||
std::string file;
|
||||
if (file_arg.find_first_of("/\\") != std::string::npos)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ namespace spot
|
|||
// \a verbose whether to output verbose messages
|
||||
SPOT_API kripke_ptr
|
||||
load_ltsmin(const std::string& file, const bdd_dict_ptr& dict,
|
||||
const ltl::atomic_prop_set* to_observe,
|
||||
ltl::formula dead = ltl::formula::tt(),
|
||||
const atomic_prop_set* to_observe,
|
||||
formula dead = formula::tt(),
|
||||
int compress = 0, bool verbose = true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -150,11 +150,11 @@ checked_main(int argc, char **argv)
|
|||
if (argc != 3)
|
||||
syntax(argv[0]);
|
||||
|
||||
spot::ltl::default_environment& env =
|
||||
spot::ltl::default_environment::instance();
|
||||
spot::default_environment& env =
|
||||
spot::default_environment::instance();
|
||||
|
||||
|
||||
spot::ltl::atomic_prop_set ap;
|
||||
spot::atomic_prop_set ap;
|
||||
auto dict = spot::make_bdd_dict();
|
||||
spot::const_kripke_ptr model = nullptr;
|
||||
spot::const_twa_ptr prop = nullptr;
|
||||
|
|
@ -162,16 +162,16 @@ checked_main(int argc, char **argv)
|
|||
spot::emptiness_check_instantiator_ptr echeck_inst = nullptr;
|
||||
int exit_code = 0;
|
||||
spot::postprocessor post;
|
||||
spot::ltl::formula deadf = nullptr;
|
||||
spot::ltl::formula f = nullptr;
|
||||
spot::formula deadf = nullptr;
|
||||
spot::formula f = nullptr;
|
||||
|
||||
if (!dead || !strcasecmp(dead, "true"))
|
||||
{
|
||||
deadf = spot::ltl::formula::tt();
|
||||
deadf = spot::formula::tt();
|
||||
}
|
||||
else if (!strcasecmp(dead, "false"))
|
||||
{
|
||||
deadf = spot::ltl::formula::ff();
|
||||
deadf = spot::formula::ff();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -193,9 +193,9 @@ checked_main(int argc, char **argv)
|
|||
|
||||
tm.start("parsing formula");
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
f = spot::ltl::parse_infix_psl(argv[2], pel, env, false);
|
||||
exit_code = spot::ltl::format_parse_errors(std::cerr, argv[2], pel);
|
||||
spot::parse_error_list pel;
|
||||
f = spot::parse_infix_psl(argv[2], pel, env, false);
|
||||
exit_code = spot::format_parse_errors(std::cerr, argv[2], pel);
|
||||
}
|
||||
tm.stop("parsing formula");
|
||||
|
||||
|
|
@ -366,6 +366,6 @@ main(int argc, char **argv)
|
|||
auto exit_code = checked_main(argc, argv);
|
||||
|
||||
// Additional checks to debug reference counts in formulas.
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
exit(exit_code);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@ namespace
|
|||
}
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula, const char*, int)
|
||||
process_formula(spot::formula, const char*, int)
|
||||
{
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ automaton_printer::automaton_printer(stat_style input)
|
|||
|
||||
void
|
||||
automaton_printer::print(const spot::twa_graph_ptr& aut,
|
||||
spot::ltl::formula f,
|
||||
spot::formula f,
|
||||
// Input location for errors and statistics.
|
||||
const char* filename,
|
||||
int loc,
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ public:
|
|||
std::ostream&
|
||||
print(const spot::const_parsed_aut_ptr& haut,
|
||||
const spot::const_twa_graph_ptr& aut,
|
||||
spot::ltl::formula f,
|
||||
spot::formula f,
|
||||
const char* filename, int loc, double run_time)
|
||||
{
|
||||
filename_ = filename ? filename : "";
|
||||
|
|
@ -225,7 +225,7 @@ public:
|
|||
|
||||
void
|
||||
print(const spot::twa_graph_ptr& aut,
|
||||
spot::ltl::formula f = nullptr,
|
||||
spot::formula f = nullptr,
|
||||
// Input location for errors and statistics.
|
||||
const char* filename = nullptr,
|
||||
int loc = -1,
|
||||
|
|
|
|||
|
|
@ -77,14 +77,14 @@ parse_opt_finput(int key, char* arg, struct argp_state*)
|
|||
return 0;
|
||||
}
|
||||
|
||||
spot::ltl::formula
|
||||
parse_formula(const std::string& s, spot::ltl::parse_error_list& pel)
|
||||
spot::formula
|
||||
parse_formula(const std::string& s, spot::parse_error_list& pel)
|
||||
{
|
||||
if (lbt_input)
|
||||
return spot::ltl::parse_prefix_ltl(s, pel);
|
||||
return spot::parse_prefix_ltl(s, pel);
|
||||
else
|
||||
return spot::ltl::parse_infix_psl
|
||||
(s, pel, spot::ltl::default_environment::instance(), false, lenient);
|
||||
return spot::parse_infix_psl
|
||||
(s, pel, spot::default_environment::instance(), false, lenient);
|
||||
}
|
||||
|
||||
job_processor::job_processor()
|
||||
|
|
@ -109,14 +109,14 @@ job_processor::process_string(const std::string& input,
|
|||
const char* filename,
|
||||
int linenum)
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::parse_error_list pel;
|
||||
auto f = parse_formula(input, pel);
|
||||
|
||||
if (!f || !pel.empty())
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
spot::ltl::format_parse_errors(std::cerr, input, pel);
|
||||
spot::format_parse_errors(std::cerr, input, pel);
|
||||
return 1;
|
||||
}
|
||||
return process_formula(f, filename, linenum);
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ extern const struct argp finput_argp;
|
|||
|
||||
int parse_opt_finput(int key, char* arg, struct argp_state* state);
|
||||
|
||||
spot::ltl::formula
|
||||
parse_formula(const std::string& s, spot::ltl::parse_error_list& error_list);
|
||||
spot::formula
|
||||
parse_formula(const std::string& s, spot::parse_error_list& error_list);
|
||||
|
||||
|
||||
class job_processor
|
||||
|
|
@ -58,7 +58,7 @@ public:
|
|||
virtual ~job_processor();
|
||||
|
||||
virtual int
|
||||
process_formula(spot::ltl::formula f,
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0) = 0;
|
||||
|
||||
virtual int
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ const struct argp output_argp = { options, parse_opt_output,
|
|||
|
||||
static
|
||||
void
|
||||
report_not_ltl(spot::ltl::formula f,
|
||||
report_not_ltl(spot::formula f,
|
||||
const char* filename, int linenum, const char* syn)
|
||||
{
|
||||
std::string s = spot::ltl::str_psl(f);
|
||||
std::string s = spot::str_psl(f);
|
||||
static const char msg[] =
|
||||
"formula '%s' cannot be written %s's syntax because it is not LTL";
|
||||
if (filename)
|
||||
|
|
@ -84,36 +84,36 @@ report_not_ltl(spot::ltl::formula f,
|
|||
|
||||
std::ostream&
|
||||
stream_formula(std::ostream& out,
|
||||
spot::ltl::formula f, const char* filename, int linenum)
|
||||
spot::formula f, const char* filename, int linenum)
|
||||
{
|
||||
switch (output_format)
|
||||
{
|
||||
case lbt_output:
|
||||
if (f.is_ltl_formula())
|
||||
spot::ltl::print_lbt_ltl(out, f);
|
||||
spot::print_lbt_ltl(out, f);
|
||||
else
|
||||
report_not_ltl(f, filename, linenum, "LBT");
|
||||
break;
|
||||
case spot_output:
|
||||
spot::ltl::print_psl(out, f, full_parenth);
|
||||
spot::print_psl(out, f, full_parenth);
|
||||
break;
|
||||
case spin_output:
|
||||
if (f.is_ltl_formula())
|
||||
spot::ltl::print_spin_ltl(out, f, full_parenth);
|
||||
spot::print_spin_ltl(out, f, full_parenth);
|
||||
else
|
||||
report_not_ltl(f, filename, linenum, "Spin");
|
||||
break;
|
||||
case wring_output:
|
||||
if (f.is_ltl_formula())
|
||||
spot::ltl::print_wring_ltl(out, f);
|
||||
spot::print_wring_ltl(out, f);
|
||||
else
|
||||
report_not_ltl(f, filename, linenum, "Wring");
|
||||
break;
|
||||
case utf8_output:
|
||||
spot::ltl::print_utf8_psl(out, f, full_parenth);
|
||||
spot::print_utf8_psl(out, f, full_parenth);
|
||||
break;
|
||||
case latex_output:
|
||||
spot::ltl::print_latex_psl(out, f, full_parenth);
|
||||
spot::print_latex_psl(out, f, full_parenth);
|
||||
break;
|
||||
case count_output:
|
||||
case quiet_output:
|
||||
|
|
@ -124,7 +124,7 @@ stream_formula(std::ostream& out,
|
|||
|
||||
static void
|
||||
stream_escapable_formula(std::ostream& os,
|
||||
spot::ltl::formula f,
|
||||
spot::formula f,
|
||||
const char* filename, int linenum)
|
||||
{
|
||||
if (escape_csv)
|
||||
|
|
@ -146,7 +146,7 @@ namespace
|
|||
{
|
||||
struct formula_with_location
|
||||
{
|
||||
spot::ltl::formula f;
|
||||
spot::formula f;
|
||||
const char* filename;
|
||||
int line;
|
||||
const char* prefix;
|
||||
|
|
@ -260,7 +260,7 @@ parse_opt_output(int key, char* arg, struct argp_state*)
|
|||
|
||||
static void
|
||||
output_formula(std::ostream& out,
|
||||
spot::ltl::formula f,
|
||||
spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0,
|
||||
const char* prefix = nullptr, const char* suffix = nullptr)
|
||||
{
|
||||
|
|
@ -286,7 +286,7 @@ void
|
|||
}
|
||||
|
||||
void
|
||||
output_formula_checked(spot::ltl::formula f,
|
||||
output_formula_checked(spot::formula f,
|
||||
const char* filename, int linenum,
|
||||
const char* prefix, const char* suffix)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -43,20 +43,20 @@ int parse_opt_output(int key, char* arg, struct argp_state* state);
|
|||
// Low-level output
|
||||
std::ostream&
|
||||
stream_formula(std::ostream& out,
|
||||
spot::ltl::formula f, const char* filename, int linenum);
|
||||
spot::formula f, const char* filename, int linenum);
|
||||
|
||||
void output_formula_checked(spot::ltl::formula f,
|
||||
void output_formula_checked(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0,
|
||||
const char* prefix = nullptr,
|
||||
const char* suffix = nullptr);
|
||||
|
||||
|
||||
class printable_formula:
|
||||
public spot::printable_value<spot::ltl::formula>
|
||||
public spot::printable_value<spot::formula>
|
||||
{
|
||||
public:
|
||||
printable_formula&
|
||||
operator=(spot::ltl::formula new_val)
|
||||
operator=(spot::formula new_val)
|
||||
{
|
||||
val_ = new_val;
|
||||
return *this;
|
||||
|
|
@ -79,7 +79,7 @@ public:
|
|||
|
||||
std::ostream&
|
||||
print(const spot::const_twa_graph_ptr& aut,
|
||||
spot::ltl::formula f = nullptr,
|
||||
spot::formula f = nullptr,
|
||||
double run_time = -1.)
|
||||
{
|
||||
formula_ = f;
|
||||
|
|
|
|||
|
|
@ -44,4 +44,4 @@
|
|||
extern int simplification_level;
|
||||
|
||||
void parse_r(const char* arg);
|
||||
spot::ltl::ltl_simplifier_options simplifier_options();
|
||||
spot::ltl_simplifier_options simplifier_options();
|
||||
|
|
|
|||
|
|
@ -290,16 +290,16 @@ translator_runner::formula() const
|
|||
}
|
||||
|
||||
void
|
||||
translator_runner::round_formula(spot::ltl::formula f, unsigned serial)
|
||||
translator_runner::round_formula(spot::formula f, unsigned serial)
|
||||
{
|
||||
if (has('f') || has('F'))
|
||||
string_ltl_spot = spot::ltl::str_psl(f, true);
|
||||
string_ltl_spot = spot::str_psl(f, true);
|
||||
if (has('s') || has('S'))
|
||||
string_ltl_spin = spot::ltl::str_spin_ltl(f, true);
|
||||
string_ltl_spin = spot::str_spin_ltl(f, true);
|
||||
if (has('l') || has('L'))
|
||||
string_ltl_lbt = spot::ltl::str_lbt_ltl(f);
|
||||
string_ltl_lbt = spot::str_lbt_ltl(f);
|
||||
if (has('w') || has('W'))
|
||||
string_ltl_wring = spot::ltl::str_wring_ltl(f);
|
||||
string_ltl_wring = spot::str_wring_ltl(f);
|
||||
if (has('F'))
|
||||
string_to_tmp(string_ltl_spot, serial, filename_ltl_spot);
|
||||
if (has('S'))
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ public:
|
|||
bool no_output_allowed = false);
|
||||
void string_to_tmp(std::string& str, unsigned n, std::string& tmpname);
|
||||
const std::string& formula() const;
|
||||
void round_formula(spot::ltl::formula f, unsigned serial);
|
||||
void round_formula(spot::formula f, unsigned serial);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace
|
|||
}
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula, const char*, int)
|
||||
process_formula(spot::formula, const char*, int)
|
||||
{
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@
|
|||
#include "tl/relabel.hh"
|
||||
|
||||
using namespace spot;
|
||||
using namespace spot::ltl;
|
||||
|
||||
const char argp_program_doc[] ="\
|
||||
Generate temporal logic formulas from predefined scalable patterns.";
|
||||
|
|
|
|||
|
|
@ -139,16 +139,16 @@ namespace
|
|||
}
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula f,
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
// This should not happen, because the parser we use can only
|
||||
// read PSL/LTL formula, but since our ltl::formula type can
|
||||
// read PSL/LTL formula, but since our formula type can
|
||||
// represent more than PSL formula, let's make this
|
||||
// future-proof.
|
||||
if (!f.is_psl_formula())
|
||||
{
|
||||
std::string s = spot::ltl::str_psl(f);
|
||||
std::string s = spot::str_psl(f);
|
||||
error_at_line(2, 0, filename, linenum,
|
||||
"formula '%s' is not an LTL or PSL formula",
|
||||
s.c_str());
|
||||
|
|
|
|||
|
|
@ -170,18 +170,18 @@ namespace
|
|||
}
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula f,
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
auto aut = trans.run(&f);
|
||||
|
||||
// This should not happen, because the parser we use can only
|
||||
// read PSL/LTL formula, but since our ltl::formula type can
|
||||
// read PSL/LTL formula, but since our formula type can
|
||||
// represent more than PSL formula, let's make this
|
||||
// future-proof.
|
||||
if (!f.is_psl_formula())
|
||||
{
|
||||
std::string s = spot::ltl::str_psl(f);
|
||||
std::string s = spot::str_psl(f);
|
||||
error_at_line(2, 0, filename, linenum,
|
||||
"formula '%s' is not an LTL or PSL formula",
|
||||
s.c_str());
|
||||
|
|
|
|||
|
|
@ -819,7 +819,7 @@ namespace
|
|||
}
|
||||
|
||||
typedef
|
||||
std::unordered_set<spot::ltl::formula> fset_t;
|
||||
std::unordered_set<spot::formula> fset_t;
|
||||
|
||||
|
||||
class processor: public job_processor
|
||||
|
|
@ -838,14 +838,14 @@ namespace
|
|||
const char* filename,
|
||||
int linenum)
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = parse_formula(input, pel);
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = parse_formula(input, pel);
|
||||
|
||||
if (!f || !pel.empty())
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
spot::ltl::format_parse_errors(std::cerr, input, pel);
|
||||
spot::format_parse_errors(std::cerr, input, pel);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -856,7 +856,7 @@ namespace
|
|||
if (res && grind_output)
|
||||
{
|
||||
std::string bogus = input;
|
||||
std::vector<spot::ltl::formula> mutations;
|
||||
std::vector<spot::formula> mutations;
|
||||
unsigned mutation_count;
|
||||
unsigned mutation_max;
|
||||
while (res)
|
||||
|
|
@ -886,9 +886,9 @@ namespace
|
|||
if (res)
|
||||
{
|
||||
if (lbt_input)
|
||||
bogus = spot::ltl::str_lbt_ltl(f);
|
||||
bogus = spot::str_lbt_ltl(f);
|
||||
else
|
||||
bogus = spot::ltl::str_psl(f);
|
||||
bogus = spot::str_psl(f);
|
||||
if (bogus_output)
|
||||
bogus_output->ostream() << bogus << std::endl;
|
||||
}
|
||||
|
|
@ -938,7 +938,7 @@ namespace
|
|||
}
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula f,
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
static unsigned round = 0;
|
||||
|
|
@ -947,7 +947,7 @@ namespace
|
|||
// output, relabel the formula.
|
||||
if (!f.has_lbt_atomic_props() &&
|
||||
(runner.has('l') || runner.has('L') || runner.has('T')))
|
||||
f = spot::ltl::relabel(f, spot::ltl::Pnn);
|
||||
f = spot::relabel(f, spot::Pnn);
|
||||
|
||||
// ---------- Positive Formula ----------
|
||||
|
||||
|
|
@ -1028,7 +1028,7 @@ namespace
|
|||
nstats = &vstats[n + 1];
|
||||
nstats->resize(m);
|
||||
|
||||
spot::ltl::formula nf = spot::ltl::formula::Not(f);
|
||||
spot::formula nf = spot::formula::Not(f);
|
||||
|
||||
if (!allow_dups)
|
||||
{
|
||||
|
|
@ -1143,7 +1143,7 @@ namespace
|
|||
std::cerr << "Gathering statistics..." << std::endl;
|
||||
}
|
||||
|
||||
spot::ltl::atomic_prop_set* ap = spot::ltl::atomic_prop_collect(f);
|
||||
spot::atomic_prop_set* ap = spot::atomic_prop_collect(f);
|
||||
|
||||
if (want_stats)
|
||||
for (size_t i = 0; i < m; ++i)
|
||||
|
|
|
|||
|
|
@ -237,14 +237,14 @@ namespace
|
|||
const char* filename,
|
||||
int linenum)
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = parse_formula(input, pel);
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = parse_formula(input, pel);
|
||||
|
||||
if (!f || !pel.empty())
|
||||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
spot::ltl::format_parse_errors(std::cerr, input, pel);
|
||||
spot::format_parse_errors(std::cerr, input, pel);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -255,10 +255,10 @@ namespace
|
|||
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula f,
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
std::unique_ptr<spot::ltl::relabeling_map> relmap;
|
||||
std::unique_ptr<spot::relabeling_map> relmap;
|
||||
|
||||
// If atomic propositions are incompatible with one of the
|
||||
// output, relabel the formula.
|
||||
|
|
@ -267,8 +267,8 @@ namespace
|
|||
|| (!f.has_spin_atomic_props() &&
|
||||
(runner.has('s') || runner.has('S'))))
|
||||
{
|
||||
relmap.reset(new spot::ltl::relabeling_map);
|
||||
f = spot::ltl::relabel(f, spot::ltl::Pnn, relmap.get());
|
||||
relmap.reset(new spot::relabeling_map);
|
||||
f = spot::relabel(f, spot::Pnn, relmap.get());
|
||||
}
|
||||
|
||||
static unsigned round = 1;
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ static int bsize_min = -1;
|
|||
static int bsize_max = -1;
|
||||
enum relabeling_mode { NoRelabeling = 0, ApRelabeling, BseRelabeling };
|
||||
static relabeling_mode relabeling = NoRelabeling;
|
||||
static spot::ltl::relabeling_style style = spot::ltl::Abc;
|
||||
static spot::relabeling_style style = spot::Abc;
|
||||
static bool remove_x = false;
|
||||
static bool stutter_insensitive = false;
|
||||
static bool ap = false;
|
||||
|
|
@ -262,16 +262,16 @@ static spot::exclusive_ap excl_ap;
|
|||
static std::unique_ptr<output_file> output_define = nullptr;
|
||||
static std::string unabbreviate;
|
||||
|
||||
static spot::ltl::formula implied_by = nullptr;
|
||||
static spot::ltl::formula imply = nullptr;
|
||||
static spot::ltl::formula equivalent_to = nullptr;
|
||||
static spot::formula implied_by = nullptr;
|
||||
static spot::formula imply = nullptr;
|
||||
static spot::formula equivalent_to = nullptr;
|
||||
|
||||
static spot::ltl::formula
|
||||
static spot::formula
|
||||
parse_formula_arg(const std::string& input)
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = parse_formula(input, pel);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = parse_formula(input, pel);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
error(2, 0, "parse error when parsing an argument");
|
||||
return f;
|
||||
}
|
||||
|
|
@ -343,16 +343,16 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_IMPLIED_BY:
|
||||
{
|
||||
spot::ltl::formula i = parse_formula_arg(arg);
|
||||
spot::formula i = parse_formula_arg(arg);
|
||||
// a→c∧b→c ≡ (a∨b)→c
|
||||
implied_by = spot::ltl::formula::Or({implied_by, i});
|
||||
implied_by = spot::formula::Or({implied_by, i});
|
||||
break;
|
||||
}
|
||||
case OPT_IMPLY:
|
||||
{
|
||||
// a→b∧a→c ≡ a→(b∧c)
|
||||
spot::ltl::formula i = parse_formula_arg(arg);
|
||||
imply = spot::ltl::formula::And({imply, i});
|
||||
spot::formula i = parse_formula_arg(arg);
|
||||
imply = spot::formula::And({imply, i});
|
||||
break;
|
||||
}
|
||||
case OPT_LTL:
|
||||
|
|
@ -371,9 +371,9 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
case OPT_RELABEL_BOOL:
|
||||
relabeling = (key == OPT_RELABEL_BOOL ? BseRelabeling : ApRelabeling);
|
||||
if (!arg || !strncasecmp(arg, "abc", 6))
|
||||
style = spot::ltl::Abc;
|
||||
style = spot::Abc;
|
||||
else if (!strncasecmp(arg, "pnn", 4))
|
||||
style = spot::ltl::Pnn;
|
||||
style = spot::Pnn;
|
||||
else
|
||||
error(2, 0, "invalid argument for --relabel%s: '%s'",
|
||||
(key == OPT_RELABEL_BOOL ? "-bool" : ""),
|
||||
|
|
@ -404,7 +404,7 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
if (arg)
|
||||
unabbreviate += arg;
|
||||
else
|
||||
unabbreviate += spot::ltl::default_unabbrev_string;
|
||||
unabbreviate += spot::default_unabbrev_string;
|
||||
break;
|
||||
case OPT_AP_N:
|
||||
ap = true;
|
||||
|
|
@ -438,18 +438,18 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
}
|
||||
|
||||
typedef
|
||||
std::unordered_set<spot::ltl::formula> fset_t;
|
||||
std::unordered_set<spot::formula> fset_t;
|
||||
|
||||
namespace
|
||||
{
|
||||
class ltl_processor: public job_processor
|
||||
{
|
||||
public:
|
||||
spot::ltl::ltl_simplifier& simpl;
|
||||
spot::ltl_simplifier& simpl;
|
||||
fset_t unique_set;
|
||||
spot::ltl::relabeling_map relmap;
|
||||
spot::relabeling_map relmap;
|
||||
|
||||
ltl_processor(spot::ltl::ltl_simplifier& simpl)
|
||||
ltl_processor(spot::ltl_simplifier& simpl)
|
||||
: simpl(simpl)
|
||||
{
|
||||
}
|
||||
|
|
@ -458,8 +458,8 @@ namespace
|
|||
process_string(const std::string& input,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::ltl::formula f = parse_formula(input, pel);
|
||||
spot::parse_error_list pel;
|
||||
spot::formula f = parse_formula(input, pel);
|
||||
|
||||
if (!f || pel.size() > 0)
|
||||
{
|
||||
|
|
@ -467,7 +467,7 @@ namespace
|
|||
{
|
||||
if (filename)
|
||||
error_at_line(0, 0, filename, linenum, "parse error:");
|
||||
spot::ltl::format_parse_errors(std::cerr, input, pel);
|
||||
spot::format_parse_errors(std::cerr, input, pel);
|
||||
}
|
||||
|
||||
if (error_style == skip_errors)
|
||||
|
|
@ -489,7 +489,7 @@ namespace
|
|||
}
|
||||
|
||||
int
|
||||
process_formula(spot::ltl::formula f,
|
||||
process_formula(spot::formula f,
|
||||
const char* filename = nullptr, int linenum = 0)
|
||||
{
|
||||
if (opt_max_count >= 0 && match_count >= opt_max_count)
|
||||
|
|
@ -499,14 +499,14 @@ namespace
|
|||
}
|
||||
|
||||
if (negate)
|
||||
f = spot::ltl::formula::Not(f);
|
||||
f = spot::formula::Not(f);
|
||||
|
||||
if (remove_x)
|
||||
{
|
||||
// If simplification are enabled, we do them before and after.
|
||||
if (simplification_level)
|
||||
f = simpl.simplify(f);
|
||||
f = spot::ltl::remove_x(f);
|
||||
f = spot::remove_x(f);
|
||||
}
|
||||
|
||||
if (simplification_level || boolean_to_isop)
|
||||
|
|
@ -520,13 +520,13 @@ namespace
|
|||
case ApRelabeling:
|
||||
{
|
||||
relmap.clear();
|
||||
f = spot::ltl::relabel(f, style, &relmap);
|
||||
f = spot::relabel(f, style, &relmap);
|
||||
break;
|
||||
}
|
||||
case BseRelabeling:
|
||||
{
|
||||
relmap.clear();
|
||||
f = spot::ltl::relabel_bse(f, style, &relmap);
|
||||
f = spot::relabel_bse(f, style, &relmap);
|
||||
break;
|
||||
}
|
||||
case NoRelabeling:
|
||||
|
|
@ -534,7 +534,7 @@ namespace
|
|||
}
|
||||
|
||||
if (!unabbreviate.empty())
|
||||
f = spot::ltl::unabbreviate(f, unabbreviate.c_str());
|
||||
f = spot::unabbreviate(f, unabbreviate.c_str());
|
||||
|
||||
if (!excl_ap.empty())
|
||||
f = excl_ap.constrain(f);
|
||||
|
|
@ -556,14 +556,14 @@ namespace
|
|||
|
||||
if (matched && (size_min > 0 || size_max >= 0))
|
||||
{
|
||||
int l = spot::ltl::length(f);
|
||||
int l = spot::length(f);
|
||||
matched &= (size_min <= 0) || (l >= size_min);
|
||||
matched &= (size_max < 0) || (l <= size_max);
|
||||
}
|
||||
|
||||
if (matched && (bsize_min > 0 || bsize_max >= 0))
|
||||
{
|
||||
int l = spot::ltl::length_boolone(f);
|
||||
int l = spot::length_boolone(f);
|
||||
matched &= (bsize_min <= 0) || (l >= bsize_min);
|
||||
matched &= (bsize_max < 0) || (l <= bsize_max);
|
||||
}
|
||||
|
|
@ -606,7 +606,7 @@ namespace
|
|||
&& output_format != quiet_output)
|
||||
{
|
||||
// Sort the formulas alphabetically.
|
||||
std::map<std::string, spot::ltl::formula> m;
|
||||
std::map<std::string, spot::formula> m;
|
||||
for (auto& p: relmap)
|
||||
m.emplace(str_psl(p.first), p.second);
|
||||
for (auto& p: m)
|
||||
|
|
@ -641,9 +641,9 @@ main(int argc, char** argv)
|
|||
|
||||
if (boolean_to_isop && simplification_level == 0)
|
||||
simplification_level = 1;
|
||||
spot::ltl::ltl_simplifier_options opt(simplification_level);
|
||||
spot::ltl_simplifier_options opt(simplification_level);
|
||||
opt.boolean_to_isop = boolean_to_isop;
|
||||
spot::ltl::ltl_simplifier simpl(opt);
|
||||
spot::ltl_simplifier simpl(opt);
|
||||
|
||||
ltl_processor processor(simpl);
|
||||
if (processor.run())
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ enum {
|
|||
static unsigned mutation_nb = 1;
|
||||
static unsigned max_output = -1U;
|
||||
|
||||
static unsigned opt_all = spot::ltl::Mut_All;
|
||||
static unsigned opt_all = spot::Mut_All;
|
||||
static unsigned mut_opts = 0;
|
||||
static bool opt_sort = false;
|
||||
|
||||
|
|
@ -96,11 +96,11 @@ namespace
|
|||
{
|
||||
public:
|
||||
int
|
||||
process_formula(spot::ltl::formula f, const char* filename = nullptr,
|
||||
process_formula(spot::formula f, const char* filename = nullptr,
|
||||
int linenum = 0)
|
||||
{
|
||||
auto mutations =
|
||||
spot::ltl::mutate(f, mut_opts, max_output, mutation_nb, opt_sort);
|
||||
spot::mutate(f, mut_opts, max_output, mutation_nb, opt_sort);
|
||||
for (auto g: mutations)
|
||||
output_formula_checked(g, filename, linenum);
|
||||
return 0;
|
||||
|
|
@ -121,31 +121,31 @@ parse_opt(int key, char* arg, struct argp_state*)
|
|||
break;
|
||||
case OPT_AP2CONST:
|
||||
opt_all = 0;
|
||||
mut_opts |= spot::ltl::Mut_Ap2Const;
|
||||
mut_opts |= spot::Mut_Ap2Const;
|
||||
break;
|
||||
case OPT_REMOVE_ONE_AP:
|
||||
opt_all = 0;
|
||||
mut_opts |= spot::ltl::Mut_Remove_One_Ap;
|
||||
mut_opts |= spot::Mut_Remove_One_Ap;
|
||||
break;
|
||||
case OPT_REMOVE_MULTOP_OPERANDS:
|
||||
opt_all = 0;
|
||||
mut_opts |= spot::ltl::Mut_Remove_Multop_Operands;
|
||||
mut_opts |= spot::Mut_Remove_Multop_Operands;
|
||||
break;
|
||||
case OPT_REMOVE_OPS:
|
||||
opt_all = 0;
|
||||
mut_opts |= spot::ltl::Mut_Remove_Ops;
|
||||
mut_opts |= spot::Mut_Remove_Ops;
|
||||
break;
|
||||
case OPT_SPLIT_OPS:
|
||||
opt_all = 0;
|
||||
mut_opts |= spot::ltl::Mut_Split_Ops;
|
||||
mut_opts |= spot::Mut_Split_Ops;
|
||||
break;
|
||||
case OPT_REWRITE_OPS:
|
||||
opt_all = 0;
|
||||
mut_opts |= spot::ltl::Mut_Rewrite_Ops;
|
||||
mut_opts |= spot::Mut_Rewrite_Ops;
|
||||
break;
|
||||
case OPT_SIMPLIFY_BOUNDS:
|
||||
opt_all = 0;
|
||||
mut_opts |= spot::ltl::Mut_Simplify_Bounds;
|
||||
mut_opts |= spot::Mut_Simplify_Bounds;
|
||||
break;
|
||||
case OPT_SORT:
|
||||
opt_sort = true;
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ static const struct argp_child children[] =
|
|||
static const char* opt_acceptance = nullptr;
|
||||
typedef spot::twa_graph::graph_t::edge_storage_t tr_t;
|
||||
typedef std::set<std::vector<tr_t>> unique_aut_t;
|
||||
static spot::ltl::atomic_prop_set aprops;
|
||||
static spot::atomic_prop_set aprops;
|
||||
static range ap_count_given = {-1, -2}; // Must be two different negative val
|
||||
static int opt_seed = 0;
|
||||
static const char* opt_seed_str = "0";
|
||||
|
|
@ -249,10 +249,10 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
ap_count_given = parse_range(arg);
|
||||
// Create the set once if the count is fixed.
|
||||
if (ap_count_given.min == ap_count_given.max)
|
||||
aprops = spot::ltl::create_atomic_prop_set(ap_count_given.min);
|
||||
aprops = spot::create_atomic_prop_set(ap_count_given.min);
|
||||
break;
|
||||
}
|
||||
aprops.insert(spot::ltl::formula::ap(arg));
|
||||
aprops.insert(spot::formula::ap(arg));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
@ -329,7 +329,7 @@ main(int argc, char** argv)
|
|||
&& ap_count_given.min != ap_count_given.max)
|
||||
{
|
||||
int c = spot::rrand(ap_count_given.min, ap_count_given.max);
|
||||
aprops = spot::ltl::create_atomic_prop_set(c);
|
||||
aprops = spot::create_atomic_prop_set(c);
|
||||
}
|
||||
|
||||
int size = opt_states.min;
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ const struct argp_child children[] =
|
|||
{ nullptr, 0, nullptr, 0 }
|
||||
};
|
||||
|
||||
spot::ltl::atomic_prop_set aprops;
|
||||
spot::atomic_prop_set aprops;
|
||||
static int output = OUTPUTLTL;
|
||||
static char* opt_pL = nullptr;
|
||||
static char* opt_pS = nullptr;
|
||||
|
|
@ -209,11 +209,11 @@ parse_opt(int key, char* arg, struct argp_state* as)
|
|||
if (!*endptr && res >= 0) // arg is a number
|
||||
{
|
||||
ap_count_given = true;
|
||||
aprops = spot::ltl::create_atomic_prop_set(res);
|
||||
aprops = spot::create_atomic_prop_set(res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
aprops.insert(spot::ltl::default_environment::instance().require(arg));
|
||||
aprops.insert(spot::default_environment::instance().require(arg));
|
||||
break;
|
||||
default:
|
||||
return ARGP_ERR_UNKNOWN;
|
||||
|
|
@ -241,7 +241,7 @@ main(int argc, char** argv)
|
|||
spot::srand(opt_seed);
|
||||
try
|
||||
{
|
||||
spot::ltl::randltlgenerator rg
|
||||
spot::randltlgenerator rg
|
||||
(aprops,
|
||||
[&] (){
|
||||
spot::option_map opts;
|
||||
|
|
@ -292,7 +292,7 @@ main(int argc, char** argv)
|
|||
while (opt_formulas < 0 || opt_formulas--)
|
||||
{
|
||||
static int count = 0;
|
||||
spot::ltl::formula f = rg.next();
|
||||
spot::formula f = rg.next();
|
||||
if (!f)
|
||||
{
|
||||
error(2, 0, "failed to generate a new unique formula after %d " \
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ namespace spot
|
|||
}
|
||||
|
||||
|
||||
void kripke_explicit::add_condition(ltl::formula f, std::string on_me)
|
||||
void kripke_explicit::add_condition(formula f, std::string on_me)
|
||||
{
|
||||
add_conditions(formula_to_bdd(f, get_dict(), this), on_me);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ namespace spot
|
|||
///
|
||||
/// \param f the formula to add.
|
||||
/// \param on_me the state where to add.
|
||||
void add_condition(ltl::formula f, std::string on_me);
|
||||
void add_condition(formula f, std::string on_me);
|
||||
|
||||
/// \brief Return map between states and their names.
|
||||
const std::map<const state_kripke*, std::string>&
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ typedef std::map<std::string, bdd> formula_cache;
|
|||
}
|
||||
|
||||
%parse-param {spot::kripke_parse_error_list& error_list}
|
||||
%parse-param {spot::ltl::environment& parse_environment}
|
||||
%parse-param {spot::environment& parse_environment}
|
||||
%parse-param {spot::kripke_explicit_ptr& result}
|
||||
%parse-param {formula_cache& fcache}
|
||||
|
||||
|
|
@ -62,9 +62,9 @@ typedef std::map<std::string, bdd> formula_cache;
|
|||
before parsedecl.hh uses it. */
|
||||
#include "parsedecl.hh"
|
||||
|
||||
using namespace spot::ltl;
|
||||
using namespace spot;
|
||||
#include <iostream>
|
||||
//typedef std::pair<bool, spot::ltl::formula*> pair;
|
||||
//typedef std::pair<bool, spot::formula*> pair;
|
||||
}
|
||||
|
||||
%token <str> STRING UNTERMINATED_STRING IDENT
|
||||
|
|
@ -109,7 +109,7 @@ strident "," condition "," follow_list ";"
|
|||
if (i == fcache.end())
|
||||
{
|
||||
parse_error_list pel;
|
||||
formula f = spot::ltl::parse_infix_boolean(*$3, pel,
|
||||
formula f = spot::parse_infix_boolean(*$3, pel,
|
||||
parse_environment);
|
||||
for (parse_error_list::iterator i = pel.begin();
|
||||
i != pel.end(); ++i)
|
||||
|
|
@ -207,7 +207,7 @@ namespace spot
|
|||
error_list.push_back
|
||||
(kripke_parse_error(spot::location(),
|
||||
std::string("Cannot open file ") + name));
|
||||
return 0;
|
||||
return nullptr;
|
||||
}
|
||||
formula_cache fcache;
|
||||
auto result = make_kripke_explicit(dict);
|
||||
|
|
|
|||
|
|
@ -41,15 +41,15 @@ namespace spot
|
|||
kripke_parse(const std::string& name,
|
||||
kripke_parse_error_list& error_list,
|
||||
const bdd_dict_ptr& dict,
|
||||
ltl::environment& env
|
||||
= ltl::default_environment::instance(),
|
||||
environment& env
|
||||
= default_environment::instance(),
|
||||
bool debug = false);
|
||||
|
||||
|
||||
/// \brief Format diagnostics produced by spot::kripke_parse.
|
||||
/// \param os Where diagnostics should be output.
|
||||
/// \param filename The filename that should appear in the diagnostics.
|
||||
/// \param error_list The error list filled by spot::ltl::parse while
|
||||
/// \param error_list The error list filled by spot::parse while
|
||||
/// parsing \a ltl_string.
|
||||
/// \return \c true if any diagnostic was output.
|
||||
SPOT_API
|
||||
|
|
|
|||
|
|
@ -28,90 +28,85 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
void
|
||||
fix_utf8_locations(const std::string& ltl_string,
|
||||
parse_error_list& error_list)
|
||||
{
|
||||
// LUT to convert byte positions to utf8 positions.
|
||||
// (The +2 is to account for position 0, not used,
|
||||
// and position ltl_string.size()+1 denoting EOS.)
|
||||
std::vector<unsigned> b2u(ltl_string.size() + 2);
|
||||
|
||||
void
|
||||
fix_utf8_locations(const std::string& ltl_string,
|
||||
parse_error_list& error_list)
|
||||
// i will iterate over all utf8 characters between b and e
|
||||
std::string::const_iterator b = ltl_string.begin();
|
||||
std::string::const_iterator i = b;
|
||||
std::string::const_iterator e = ltl_string.end();
|
||||
|
||||
unsigned n = 0; // number of current utf8 character
|
||||
unsigned prev = 0; // last byte of previous utf8 character
|
||||
while (i != e)
|
||||
{
|
||||
utf8::next(i, e);
|
||||
++n;
|
||||
unsigned d = std::distance(b, i);
|
||||
while (prev < d)
|
||||
b2u[++prev] = n;
|
||||
}
|
||||
b2u[++prev] = ++n;
|
||||
|
||||
// use b2u to update error_list
|
||||
parse_error_list::iterator it;
|
||||
for (it = error_list.begin(); it != error_list.end(); ++it)
|
||||
{
|
||||
location& l = it->first;
|
||||
l.begin.column = b2u[l.begin.column];
|
||||
l.end.column = b2u[l.end.column];
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool
|
||||
format_parse_errors_aux(std::ostream& os,
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list)
|
||||
{
|
||||
// LUT to convert byte positions to utf8 positions.
|
||||
// (The +2 is to account for position 0, not used,
|
||||
// and position ltl_string.size()+1 denoting EOS.)
|
||||
std::vector<unsigned> b2u(ltl_string.size() + 2);
|
||||
|
||||
// i will iterate over all utf8 characters between b and e
|
||||
std::string::const_iterator b = ltl_string.begin();
|
||||
std::string::const_iterator i = b;
|
||||
std::string::const_iterator e = ltl_string.end();
|
||||
|
||||
unsigned n = 0; // number of current utf8 character
|
||||
unsigned prev = 0; // last byte of previous utf8 character
|
||||
while (i != e)
|
||||
{
|
||||
utf8::next(i, e);
|
||||
++n;
|
||||
unsigned d = std::distance(b, i);
|
||||
while (prev < d)
|
||||
b2u[++prev] = n;
|
||||
}
|
||||
b2u[++prev] = ++n;
|
||||
|
||||
// use b2u to update error_list
|
||||
parse_error_list::iterator it;
|
||||
bool printed = false;
|
||||
parse_error_list::const_iterator it;
|
||||
for (it = error_list.begin(); it != error_list.end(); ++it)
|
||||
{
|
||||
location& l = it->first;
|
||||
l.begin.column = b2u[l.begin.column];
|
||||
l.end.column = b2u[l.end.column];
|
||||
}
|
||||
}
|
||||
os << ">>> " << ltl_string << std::endl;
|
||||
const location& l = it->first;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool
|
||||
format_parse_errors_aux(std::ostream& os,
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list)
|
||||
{
|
||||
bool printed = false;
|
||||
parse_error_list::const_iterator it;
|
||||
for (it = error_list.begin(); it != error_list.end(); ++it)
|
||||
{
|
||||
os << ">>> " << ltl_string << std::endl;
|
||||
const location& l = it->first;
|
||||
|
||||
unsigned n = 1;
|
||||
for (; n < 4 + l.begin.column; ++n)
|
||||
os << ' ';
|
||||
// Write at least one '^', even if begin==end.
|
||||
unsigned n = 1;
|
||||
for (; n < 4 + l.begin.column; ++n)
|
||||
os << ' ';
|
||||
// Write at least one '^', even if begin==end.
|
||||
os << '^';
|
||||
++n;
|
||||
for (; n < 4 + l.end.column; ++n)
|
||||
os << '^';
|
||||
++n;
|
||||
for (; n < 4 + l.end.column; ++n)
|
||||
os << '^';
|
||||
os << std::endl << it->second << std::endl << std::endl;
|
||||
printed = true;
|
||||
}
|
||||
return printed;
|
||||
os << std::endl << it->second << std::endl << std::endl;
|
||||
printed = true;
|
||||
}
|
||||
return printed;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
format_parse_errors(std::ostream& os,
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list)
|
||||
{
|
||||
if (utf8::is_valid(ltl_string.begin(), ltl_string.end()))
|
||||
{
|
||||
parse_error_list fixed = error_list;
|
||||
fix_utf8_locations(ltl_string, fixed);
|
||||
return format_parse_errors_aux(os, ltl_string, fixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
return format_parse_errors_aux(os, ltl_string, error_list);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
format_parse_errors(std::ostream& os,
|
||||
const std::string& ltl_string,
|
||||
const parse_error_list& error_list)
|
||||
{
|
||||
if (utf8::is_valid(ltl_string.begin(), ltl_string.end()))
|
||||
{
|
||||
parse_error_list fixed = error_list;
|
||||
fix_utf8_locations(ltl_string, fixed);
|
||||
return format_parse_errors_aux(os, ltl_string, fixed);
|
||||
}
|
||||
else
|
||||
{
|
||||
return format_parse_errors_aux(os, ltl_string, error_list);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
%debug
|
||||
%error-verbose
|
||||
%expect 0
|
||||
%lex-param { spot::ltl::parse_error_list& error_list }
|
||||
%lex-param { spot::parse_error_list& error_list }
|
||||
%define api.location.type "spot::location"
|
||||
|
||||
%code requires
|
||||
|
|
@ -41,13 +41,13 @@
|
|||
struct minmax_t { unsigned min, max; };
|
||||
}
|
||||
|
||||
%parse-param {spot::ltl::parse_error_list &error_list}
|
||||
%parse-param {spot::ltl::environment &parse_environment}
|
||||
%parse-param {spot::ltl::formula &result}
|
||||
%parse-param {spot::parse_error_list &error_list}
|
||||
%parse-param {spot::environment &parse_environment}
|
||||
%parse-param {spot::formula &result}
|
||||
%union
|
||||
{
|
||||
std::string* str;
|
||||
const spot::ltl::fnode* ltl;
|
||||
const spot::fnode* ltl;
|
||||
unsigned num;
|
||||
minmax_t minmax;
|
||||
}
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
We mut ensure that YYSTYPE is declared (by the above %union)
|
||||
before parsedecl.hh uses it. */
|
||||
#include "parsedecl.hh"
|
||||
using namespace spot::ltl;
|
||||
using namespace spot;
|
||||
|
||||
#define missing_right_op_msg(op, str) \
|
||||
error_list.emplace_back(op, \
|
||||
|
|
@ -94,10 +94,10 @@ using namespace spot::ltl;
|
|||
static formula
|
||||
try_recursive_parse(const std::string& str,
|
||||
const spot::location& location,
|
||||
spot::ltl::environment& env,
|
||||
spot::environment& env,
|
||||
bool debug,
|
||||
parser_type type,
|
||||
spot::ltl::parse_error_list& error_list)
|
||||
spot::parse_error_list& error_list)
|
||||
{
|
||||
// We want to parse a U (b U c) as two until operators applied
|
||||
// to the atomic propositions a, b, and c. We also want to
|
||||
|
|
@ -120,18 +120,18 @@ using namespace spot::ltl;
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
spot::ltl::parse_error_list suberror;
|
||||
spot::parse_error_list suberror;
|
||||
formula f;
|
||||
switch (type)
|
||||
{
|
||||
case parser_sere:
|
||||
f = spot::ltl::parse_infix_sere(str, suberror, env, debug, true);
|
||||
f = spot::parse_infix_sere(str, suberror, env, debug, true);
|
||||
break;
|
||||
case parser_bool:
|
||||
f = spot::ltl::parse_infix_boolean(str, suberror, env, debug, true);
|
||||
f = spot::parse_infix_boolean(str, suberror, env, debug, true);
|
||||
break;
|
||||
case parser_ltl:
|
||||
f = spot::ltl::parse_infix_psl(str, suberror, env, debug, true);
|
||||
f = spot::parse_infix_psl(str, suberror, env, debug, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -237,8 +237,8 @@ using namespace spot::ltl;
|
|||
%destructor { $$->destroy(); } <ltl>
|
||||
|
||||
%printer { debug_stream() << *$$; } <str>
|
||||
%printer { spot::ltl::print_psl(debug_stream(), formula($$)); } <ltl>
|
||||
%printer { spot::ltl::print_sere(debug_stream(), formula($$)); } sere bracedsere
|
||||
%printer { print_psl(debug_stream(), formula($$)); } <ltl>
|
||||
%printer { print_sere(debug_stream(), formula($$)); } sere bracedsere
|
||||
%printer { debug_stream() << $$; } <num>
|
||||
%printer { debug_stream() << $$.min << ".." << $$.max; } <minmax>
|
||||
|
||||
|
|
@ -993,95 +993,91 @@ ltlyy::parser::error(const location_type& location, const std::string& message)
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
formula
|
||||
parse_infix_psl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug, bool lenient)
|
||||
{
|
||||
formula
|
||||
parse_infix_psl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug, bool lenient)
|
||||
{
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(ltl_string,
|
||||
ltlyy::parser::token::START_LTL,
|
||||
lenient);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(ltl_string,
|
||||
ltlyy::parser::token::START_LTL,
|
||||
lenient);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
|
||||
formula
|
||||
parse_infix_boolean(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug, bool lenient)
|
||||
{
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(ltl_string,
|
||||
ltlyy::parser::token::START_BOOL,
|
||||
lenient);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
formula
|
||||
parse_infix_boolean(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug, bool lenient)
|
||||
{
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(ltl_string,
|
||||
ltlyy::parser::token::START_BOOL,
|
||||
lenient);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
|
||||
formula
|
||||
parse_prefix_ltl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug)
|
||||
{
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(ltl_string,
|
||||
ltlyy::parser::token::START_LBT,
|
||||
false);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
formula
|
||||
parse_prefix_ltl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug)
|
||||
{
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(ltl_string,
|
||||
ltlyy::parser::token::START_LBT,
|
||||
false);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
|
||||
formula
|
||||
parse_infix_sere(const std::string& sere_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug,
|
||||
bool lenient)
|
||||
{
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(sere_string,
|
||||
ltlyy::parser::token::START_SERE,
|
||||
lenient);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
|
||||
formula
|
||||
parse_formula(const std::string& ltl_string, environment& env)
|
||||
{
|
||||
parse_error_list pel;
|
||||
formula f = parse_infix_psl(ltl_string, pel, env);
|
||||
std::ostringstream s;
|
||||
if (format_parse_errors(s, ltl_string, pel))
|
||||
{
|
||||
parse_error_list pel2;
|
||||
formula g = parse_prefix_ltl(ltl_string, pel2, env);
|
||||
if (pel2.empty())
|
||||
return g;
|
||||
else
|
||||
throw parse_error(s.str());
|
||||
}
|
||||
return f;
|
||||
}
|
||||
formula
|
||||
parse_infix_sere(const std::string& sere_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env,
|
||||
bool debug,
|
||||
bool lenient)
|
||||
{
|
||||
formula result = nullptr;
|
||||
flex_set_buffer(sere_string,
|
||||
ltlyy::parser::token::START_SERE,
|
||||
lenient);
|
||||
ltlyy::parser parser(error_list, env, result);
|
||||
parser.set_debug_level(debug);
|
||||
parser.parse();
|
||||
flex_unset_buffer();
|
||||
return result;
|
||||
}
|
||||
|
||||
formula
|
||||
parse_formula(const std::string& ltl_string, environment& env)
|
||||
{
|
||||
parse_error_list pel;
|
||||
formula f = parse_infix_psl(ltl_string, pel, env);
|
||||
std::ostringstream s;
|
||||
if (format_parse_errors(s, ltl_string, pel))
|
||||
{
|
||||
parse_error_list pel2;
|
||||
formula g = parse_prefix_ltl(ltl_string, pel2, env);
|
||||
if (pel2.empty())
|
||||
return g;
|
||||
else
|
||||
throw parse_error(s.str());
|
||||
}
|
||||
return f;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ eol2 (\n\r)+|(\r\n)+
|
|||
<<EOF>> {
|
||||
BEGIN(orig_cond);
|
||||
error_list.push_back(
|
||||
spot::ltl::one_parse_error(*yylloc,
|
||||
spot::one_parse_error(*yylloc,
|
||||
"unclosed comment"));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -141,7 +141,7 @@ eol2 (\n\r)+|(\r\n)+
|
|||
unput(')');
|
||||
if (!missing_parent)
|
||||
error_list.push_back(
|
||||
spot::ltl::one_parse_error(*yylloc,
|
||||
spot::one_parse_error(*yylloc,
|
||||
"missing closing parenthese"));
|
||||
missing_parent = true;
|
||||
}
|
||||
|
|
@ -195,7 +195,7 @@ eol2 (\n\r)+|(\r\n)+
|
|||
unput(')');
|
||||
if (!missing_parent)
|
||||
error_list.push_back(
|
||||
spot::ltl::one_parse_error(*yylloc,
|
||||
spot::one_parse_error(*yylloc,
|
||||
"missing closing brace"));
|
||||
missing_parent = true;
|
||||
}
|
||||
|
|
@ -238,7 +238,7 @@ eol2 (\n\r)+|(\r\n)+
|
|||
if (errno || yylval->num != n)
|
||||
{
|
||||
error_list.push_back(
|
||||
spot::ltl::one_parse_error(*yylloc,
|
||||
spot::one_parse_error(*yylloc,
|
||||
"value too large ignored"));
|
||||
// Skip this number and read next token
|
||||
yylloc->step();
|
||||
|
|
@ -347,7 +347,7 @@ eol2 (\n\r)+|(\r\n)+
|
|||
[^\\\"\n\r]+ s.append(yytext, yyleng);
|
||||
<<EOF>> {
|
||||
error_list.push_back(
|
||||
spot::ltl::one_parse_error(*yylloc,
|
||||
spot::one_parse_error(*yylloc,
|
||||
"unclosed string"));
|
||||
BEGIN(orig_cond);
|
||||
yylval->str = new std::string(s);
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
# define YY_DECL \
|
||||
int ltlyylex (ltlyy::parser::semantic_type *yylval, \
|
||||
spot::location *yylloc, \
|
||||
spot::ltl::parse_error_list& error_list)
|
||||
spot::parse_error_list& error_list)
|
||||
YY_DECL;
|
||||
|
||||
void flex_set_buffer(const std::string& buf, int start_tok, bool lenient);
|
||||
|
|
|
|||
|
|
@ -32,180 +32,177 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \addtogroup ltl_io
|
||||
/// @{
|
||||
/// \addtogroup ltl_io
|
||||
/// @{
|
||||
|
||||
#ifndef SWIG
|
||||
/// \brief A parse diagnostic with its location.
|
||||
typedef std::pair<location, std::string> one_parse_error;
|
||||
/// \brief A list of parser diagnostics, as filled by parse.
|
||||
typedef std::list<one_parse_error> parse_error_list;
|
||||
/// \brief A parse diagnostic with its location.
|
||||
typedef std::pair<location, std::string> one_parse_error;
|
||||
/// \brief A list of parser diagnostics, as filled by parse.
|
||||
typedef std::list<one_parse_error> parse_error_list;
|
||||
#else
|
||||
// Turn parse_error_list into an opaque type for Swig.
|
||||
struct parse_error_list {};
|
||||
// Turn parse_error_list into an opaque type for Swig.
|
||||
struct parse_error_list {};
|
||||
#endif
|
||||
|
||||
/// \brief Build a formula from an LTL string.
|
||||
/// \param ltl_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \param lenient When true, parenthesized blocks that cannot be
|
||||
/// parsed as subformulas will be considered as
|
||||
/// atomic propositions.
|
||||
/// \return A formula built from \a ltl_string, or
|
||||
/// formula(nullptr) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return a non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_infix_psl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
/// \brief Build a formula from an LTL string.
|
||||
/// \param ltl_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \param lenient When true, parenthesized blocks that cannot be
|
||||
/// parsed as subformulas will be considered as
|
||||
/// atomic propositions.
|
||||
/// \return A formula built from \a ltl_string, or
|
||||
/// formula(nullptr) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return a non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_infix_psl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Build a Boolean formula from a string.
|
||||
/// \param ltl_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \param lenient When true, parenthesized blocks that cannot be
|
||||
/// parsed as subformulas will be considered as
|
||||
/// atomic propositions.
|
||||
/// \return A formula built from \a ltl_string, or
|
||||
/// formula(nullptr) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return a non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_infix_boolean(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
/// \brief Build a Boolean formula from a string.
|
||||
/// \param ltl_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \param lenient When true, parenthesized blocks that cannot be
|
||||
/// parsed as subformulas will be considered as
|
||||
/// atomic propositions.
|
||||
/// \return A formula built from \a ltl_string, or
|
||||
/// formula(nullptr) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return a non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_infix_boolean(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Build a formula from an LTL string in LBT's format.
|
||||
/// \param ltl_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \return A formula built from \a ltl_string, or
|
||||
/// formula(nullptr) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return an non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// The LBT syntax, also used by the lbtt and scheck tools, is
|
||||
/// extended to support W, and M operators (as done in lbtt), and
|
||||
/// double-quoted atomic propositions that do not start with 'p'.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_prefix_ltl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
/// \brief Build a formula from an LTL string in LBT's format.
|
||||
/// \param ltl_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \return A formula built from \a ltl_string, or
|
||||
/// formula(nullptr) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return an non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// The LBT syntax, also used by the lbtt and scheck tools, is
|
||||
/// extended to support W, and M operators (as done in lbtt), and
|
||||
/// double-quoted atomic propositions that do not start with 'p'.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_prefix_ltl(const std::string& ltl_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
|
||||
/// \brief A simple wrapper to parse_infix_psl() and parse_prefix_ltl().
|
||||
///
|
||||
/// This is mostly meant for interactive use. It first tries
|
||||
/// parse_infix_psl(); if this fails it tries parse_prefix_ltl();
|
||||
/// and if both fails it returns the errors of the first call to
|
||||
/// parse_infix_psl() as a parse_error exception.
|
||||
SPOT_API formula
|
||||
parse_formula(const std::string& ltl_string,
|
||||
environment& env = default_environment::instance());
|
||||
/// \brief A simple wrapper to parse_infix_psl() and parse_prefix_ltl().
|
||||
///
|
||||
/// This is mostly meant for interactive use. It first tries
|
||||
/// parse_infix_psl(); if this fails it tries parse_prefix_ltl();
|
||||
/// and if both fails it returns the errors of the first call to
|
||||
/// parse_infix_psl() as a parse_error exception.
|
||||
SPOT_API formula
|
||||
parse_formula(const std::string& ltl_string,
|
||||
environment& env = default_environment::instance());
|
||||
|
||||
/// \brief Build a formula from a string representing a SERE.
|
||||
/// \param sere_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \param lenient When true, parenthesized blocks that cannot be
|
||||
/// parsed as subformulas will be considered as
|
||||
/// atomic propositions.
|
||||
/// \return A formula built from \a sere_string, or
|
||||
/// formula(0) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return an non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_infix_sere(const std::string& sere_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
/// \brief Build a formula from a string representing a SERE.
|
||||
/// \param sere_string The string to parse.
|
||||
/// \param error_list A list that will be filled with
|
||||
/// parse errors that occured during parsing.
|
||||
/// \param env The environment into which parsing should take place.
|
||||
/// \param debug When true, causes the parser to trace its execution.
|
||||
/// \param lenient When true, parenthesized blocks that cannot be
|
||||
/// parsed as subformulas will be considered as
|
||||
/// atomic propositions.
|
||||
/// \return A formula built from \a sere_string, or
|
||||
/// formula(0) if the input was unparsable.
|
||||
///
|
||||
/// Note that the parser usually tries to recover from errors. It can
|
||||
/// return an non zero value even if it encountered error during the
|
||||
/// parsing of \a ltl_string. If you want to make sure \a ltl_string
|
||||
/// was parsed succesfully, check \a error_list for emptiness.
|
||||
///
|
||||
/// \warning This function is not reentrant.
|
||||
SPOT_API
|
||||
formula parse_infix_sere(const std::string& sere_string,
|
||||
parse_error_list& error_list,
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false,
|
||||
bool lenient = false);
|
||||
|
||||
/// \brief Format diagnostics produced by spot::ltl::parse
|
||||
/// or spot::ltl::ratexp
|
||||
///
|
||||
/// If the string is utf8 encoded, spot::ltl::fix_utf8_locations()
|
||||
/// will be used to report correct utf8 locations (assuming the
|
||||
/// output is utf8 aware). Nonetheless, the supplied \a
|
||||
/// error_list will not be modified.
|
||||
///
|
||||
/// \param os Where diagnostics should be output.
|
||||
/// \param input_string The string that were parsed.
|
||||
/// \param error_list The error list filled by spot::ltl::parse
|
||||
/// or spot::ltl::parse_sere while parsing \a input_string.
|
||||
/// \return \c true iff any diagnostic was output.
|
||||
SPOT_API
|
||||
bool format_parse_errors(std::ostream& os,
|
||||
const std::string& input_string,
|
||||
const parse_error_list& error_list);
|
||||
/// \brief Format diagnostics produced by spot::parse
|
||||
/// or spot::ratexp
|
||||
///
|
||||
/// If the string is utf8 encoded, spot::fix_utf8_locations()
|
||||
/// will be used to report correct utf8 locations (assuming the
|
||||
/// output is utf8 aware). Nonetheless, the supplied \a
|
||||
/// error_list will not be modified.
|
||||
///
|
||||
/// \param os Where diagnostics should be output.
|
||||
/// \param input_string The string that were parsed.
|
||||
/// \param error_list The error list filled by spot::parse
|
||||
/// or spot::parse_sere while parsing \a input_string.
|
||||
/// \return \c true iff any diagnostic was output.
|
||||
SPOT_API
|
||||
bool format_parse_errors(std::ostream& os,
|
||||
const std::string& input_string,
|
||||
const parse_error_list& error_list);
|
||||
|
||||
/// \brief Fix location of diagnostics assuming the input is utf8.
|
||||
///
|
||||
/// The different parser functions return a parse_error_list that
|
||||
/// contain locations specified at the byte level. Although these
|
||||
/// parser recognize some utf8 characters they only work byte by
|
||||
/// byte and will report positions by counting byte.
|
||||
///
|
||||
/// This function fixes the positions returned by the parser to
|
||||
/// look correct when the string is interpreted as a utf8-encoded
|
||||
/// string.
|
||||
///
|
||||
/// It is invalid to call this function on a string that is not
|
||||
/// valid utf8.
|
||||
///
|
||||
/// You should NOT call this function before calling
|
||||
/// spot::ltl::format_parse_errors() because it is already called
|
||||
/// inside if needed. You may need this function only if you want
|
||||
/// to write your own error reporting code.
|
||||
///
|
||||
/// \param input_string The string that were parsed.
|
||||
/// \param error_list The error list filled by spot::ltl::parse
|
||||
/// or spot::ltl::parse_sere while parsing \a input_string.
|
||||
SPOT_API
|
||||
void
|
||||
fix_utf8_locations(const std::string& input_string,
|
||||
parse_error_list& error_list);
|
||||
/// \brief Fix location of diagnostics assuming the input is utf8.
|
||||
///
|
||||
/// The different parser functions return a parse_error_list that
|
||||
/// contain locations specified at the byte level. Although these
|
||||
/// parser recognize some utf8 characters they only work byte by
|
||||
/// byte and will report positions by counting byte.
|
||||
///
|
||||
/// This function fixes the positions returned by the parser to
|
||||
/// look correct when the string is interpreted as a utf8-encoded
|
||||
/// string.
|
||||
///
|
||||
/// It is invalid to call this function on a string that is not
|
||||
/// valid utf8.
|
||||
///
|
||||
/// You should NOT call this function before calling
|
||||
/// spot::format_parse_errors() because it is already called
|
||||
/// inside if needed. You may need this function only if you want
|
||||
/// to write your own error reporting code.
|
||||
///
|
||||
/// \param input_string The string that were parsed.
|
||||
/// \param error_list The error list filled by spot::parse
|
||||
/// or spot::parse_sere while parsing \a input_string.
|
||||
SPOT_API
|
||||
void
|
||||
fix_utf8_locations(const std::string& input_string,
|
||||
parse_error_list& error_list);
|
||||
|
||||
/// @}
|
||||
}
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
typedef std::map<int, bdd> map_t;
|
||||
|
||||
/* Cache parsed formulae. Labels on arcs are frequently identical
|
||||
and it would be a waste of time to parse them to ltl::formula
|
||||
and it would be a waste of time to parse them to formula
|
||||
over and over, and to register all their atomic_propositions in
|
||||
the bdd_dict. Keep the bdd result around so we can reuse
|
||||
it. */
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
spot::location used_loc;
|
||||
};
|
||||
spot::parsed_aut_ptr h;
|
||||
spot::ltl::environment* env;
|
||||
spot::environment* env;
|
||||
formula_cache fcache;
|
||||
named_tgba_t* namer = nullptr;
|
||||
spot::acc_mapper_int* acc_mapper = nullptr;
|
||||
|
|
@ -1403,8 +1403,8 @@ nc-formula: nc-formula-or-ident
|
|||
auto i = res.fcache.find(*$1);
|
||||
if (i == res.fcache.end())
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
auto f = spot::ltl::parse_infix_boolean(*$1, pel, *res.env,
|
||||
spot::parse_error_list pel;
|
||||
auto f = spot::parse_infix_boolean(*$1, pel, *res.env,
|
||||
debug_level(), true);
|
||||
for (auto& j: pel)
|
||||
{
|
||||
|
|
@ -1578,8 +1578,8 @@ lbtt-acc: { $$ = 0U; }
|
|||
}
|
||||
lbtt-guard: STRING
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
auto f = spot::ltl::parse_prefix_ltl(*$1, pel, *res.env);
|
||||
spot::parse_error_list pel;
|
||||
auto f = spot::parse_prefix_ltl(*$1, pel, *res.env);
|
||||
if (!f || !pel.empty())
|
||||
{
|
||||
std::string s = "failed to parse guard: ";
|
||||
|
|
@ -1884,7 +1884,7 @@ namespace spot
|
|||
parsed_aut_ptr
|
||||
automaton_stream_parser::parse(parse_aut_error_list& error_list,
|
||||
const bdd_dict_ptr& dict,
|
||||
ltl::environment& env,
|
||||
environment& env,
|
||||
bool debug)
|
||||
{
|
||||
restart:
|
||||
|
|
@ -1927,7 +1927,7 @@ namespace spot
|
|||
|
||||
twa_graph_ptr
|
||||
automaton_stream_parser::parse_strict(const bdd_dict_ptr& dict,
|
||||
ltl::environment& env,
|
||||
environment& env,
|
||||
bool debug)
|
||||
{
|
||||
parse_aut_error_list pel;
|
||||
|
|
|
|||
|
|
@ -79,13 +79,13 @@ namespace spot
|
|||
~automaton_stream_parser();
|
||||
parsed_aut_ptr parse(parse_aut_error_list& error_list,
|
||||
const bdd_dict_ptr& dict,
|
||||
ltl::environment& env =
|
||||
ltl::default_environment::instance(),
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
// Raises a parse_error on any syntax error
|
||||
twa_graph_ptr parse_strict(const bdd_dict_ptr& dict,
|
||||
ltl::environment& env =
|
||||
ltl::default_environment::instance(),
|
||||
environment& env =
|
||||
default_environment::instance(),
|
||||
bool debug = false);
|
||||
};
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ namespace spot
|
|||
parse_aut(const std::string& filename,
|
||||
parse_aut_error_list& error_list,
|
||||
const bdd_dict_ptr& dict,
|
||||
ltl::environment& env = ltl::default_environment::instance(),
|
||||
environment& env = default_environment::instance(),
|
||||
bool debug = false)
|
||||
{
|
||||
try
|
||||
|
|
@ -138,7 +138,7 @@ namespace spot
|
|||
/// \brief Format diagnostics produced by spot::parse_aut.
|
||||
/// \param os Where diagnostics should be output.
|
||||
/// \param filename The filename that should appear in the diagnostics.
|
||||
/// \param error_list The error list filled by spot::ltl::parse while
|
||||
/// \param error_list The error list filled by spot::parse while
|
||||
/// parsing \a ltl_string.
|
||||
/// \return \c true iff any diagnostic was output.
|
||||
SPOT_API bool
|
||||
|
|
|
|||
|
|
@ -60,13 +60,13 @@ main(int argc, char** argv)
|
|||
if (s.empty() || s[0] == '#') // Skip comments
|
||||
continue;
|
||||
|
||||
spot::ltl::parse_error_list pe;
|
||||
auto fpos = spot::ltl::parse_infix_psl(s, pe);
|
||||
spot::parse_error_list pe;
|
||||
auto fpos = spot::parse_infix_psl(s, pe);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, s, pe))
|
||||
if (spot::format_parse_errors(std::cerr, s, pe))
|
||||
return 2;
|
||||
|
||||
auto fneg = spot::ltl::formula::Not(fpos);
|
||||
auto fneg = spot::formula::Not(fpos);
|
||||
|
||||
{
|
||||
auto apos = scc_filter(ltl_to_tgba_fm(fpos, d));
|
||||
|
|
@ -104,6 +104,6 @@ main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,10 +83,10 @@ main(int argc, char** argv)
|
|||
if (s.empty() || s[0] == '#') // Skip comments
|
||||
continue;
|
||||
|
||||
spot::ltl::parse_error_list pe;
|
||||
auto f = spot::ltl::parse_infix_psl(s, pe);
|
||||
spot::parse_error_list pe;
|
||||
auto f = spot::parse_infix_psl(s, pe);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, s, pe))
|
||||
if (spot::format_parse_errors(std::cerr, s, pe))
|
||||
return 2;
|
||||
|
||||
|
||||
|
|
@ -220,6 +220,6 @@ main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ int main(int argc, char* argv[])
|
|||
auto dict = spot::make_bdd_dict();
|
||||
if (print_automaton || print_safra)
|
||||
{
|
||||
spot::ltl::environment& env(spot::ltl::default_environment::instance());
|
||||
spot::environment& env(spot::default_environment::instance());
|
||||
spot::parse_aut_error_list pel;
|
||||
auto h = spot::parse_aut(file, pel, dict, env);
|
||||
if (spot::format_parse_aut_errors(std::cerr, file, pel))
|
||||
|
|
@ -147,10 +147,10 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
else if (print_formula)
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(file, p1);
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_psl(file, p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, file, p1))
|
||||
if (spot::format_parse_errors(std::cerr, file, p1))
|
||||
return 2;
|
||||
|
||||
auto a = spot::ltl_to_tgba_fm(f1, dict);
|
||||
|
|
@ -162,14 +162,14 @@ int main(int argc, char* argv[])
|
|||
else if (stats)
|
||||
{
|
||||
spot::twa_graph_ptr a;
|
||||
spot::ltl::formula f1 = nullptr;
|
||||
spot::formula f1 = nullptr;
|
||||
|
||||
if (formula)
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
f1 = spot::ltl::parse_infix_psl(file, p1);
|
||||
spot::parse_error_list p1;
|
||||
f1 = spot::parse_infix_psl(file, p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, file, p1))
|
||||
if (spot::format_parse_errors(std::cerr, file, p1))
|
||||
return 2;
|
||||
|
||||
a = spot::ltl_to_tgba_fm(f1, dict);
|
||||
|
|
@ -177,7 +177,7 @@ int main(int argc, char* argv[])
|
|||
else
|
||||
{
|
||||
spot::parse_aut_error_list pel;
|
||||
spot::ltl::environment& env(spot::ltl::default_environment::instance());
|
||||
spot::environment& env(spot::default_environment::instance());
|
||||
auto h = spot::parse_aut(file, pel, dict, env);
|
||||
if (spot::format_parse_aut_errors(std::cerr, file, pel))
|
||||
return 2;
|
||||
|
|
@ -209,7 +209,7 @@ int main(int argc, char* argv[])
|
|||
|
||||
if (formula)
|
||||
{
|
||||
auto a2 = spot::ltl_to_tgba_fm(spot::ltl::formula::Not(f1), dict);
|
||||
auto a2 = spot::ltl_to_tgba_fm(spot::formula::Not(f1), dict);
|
||||
spot::tgba_statistics a_size = spot::stats_reachable(a2);
|
||||
std::cout << "Not Formula: "
|
||||
<< a_size.states << ", "
|
||||
|
|
@ -220,14 +220,14 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
else
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(file, p1);
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_psl(file, p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, file, p1))
|
||||
if (spot::format_parse_errors(std::cerr, file, p1))
|
||||
return 2;
|
||||
|
||||
auto Af = spot::ltl_to_tgba_fm(f1, dict);
|
||||
auto nf1 = spot::ltl::formula::Not(f1);
|
||||
auto nf1 = spot::formula::Not(f1);
|
||||
auto Anf = spot::ltl_to_tgba_fm(nf1, dict);
|
||||
auto nAf = spot::make_safra_complement(Af);
|
||||
auto nAnf = spot::make_safra_complement(Anf);
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ main(int argc, char **argv)
|
|||
std::getline(ss, form, ',');
|
||||
ss >> expected;
|
||||
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_sere(form, p1);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, form, p1))
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_sere(form, p1);
|
||||
if (spot::format_parse_errors(std::cerr, form, p1))
|
||||
return 2;
|
||||
|
||||
bool b = f1.accepts_eword();
|
||||
|
|
@ -73,6 +73,6 @@ main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -89,9 +89,9 @@ main(int argc, char** argv)
|
|||
|
||||
int runs = atoi(tokens[0].c_str());
|
||||
|
||||
spot::ltl::parse_error_list pe;
|
||||
auto f = spot::ltl::parse_infix_psl(tokens[1], pe);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, tokens[1], pe))
|
||||
spot::parse_error_list pe;
|
||||
auto f = spot::parse_infix_psl(tokens[1], pe);
|
||||
if (spot::format_parse_errors(std::cerr, tokens[1], pe))
|
||||
return 2;
|
||||
|
||||
auto d = spot::make_bdd_dict();
|
||||
|
|
@ -199,6 +199,6 @@ main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,47 +95,47 @@ main(int argc, char** argv)
|
|||
return 2;
|
||||
}
|
||||
|
||||
spot::ltl::parse_error_list p2;
|
||||
auto f2 = spot::ltl::parse_infix_psl(formulas[size - 1], p2);
|
||||
spot::parse_error_list p2;
|
||||
auto f2 = spot::parse_infix_psl(formulas[size - 1], p2);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, formulas[size - 1], p2))
|
||||
if (spot::format_parse_errors(std::cerr, formulas[size - 1], p2))
|
||||
return 2;
|
||||
|
||||
for (unsigned n = 0; n < size - 1; ++n)
|
||||
{
|
||||
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(formulas[n], p1);
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_psl(formulas[n], p1);
|
||||
|
||||
if (check_first &&
|
||||
spot::ltl::format_parse_errors(std::cerr, formulas[n], p1))
|
||||
spot::format_parse_errors(std::cerr, formulas[n], p1))
|
||||
return 2;
|
||||
|
||||
int exit_code = 0;
|
||||
|
||||
{
|
||||
#if defined UNABBREV || defined NENOFORM
|
||||
spot::ltl::formula tmp;
|
||||
spot::formula tmp;
|
||||
#endif
|
||||
#ifdef UNABBREV
|
||||
tmp = f1;
|
||||
f1 = spot::ltl::unabbreviate(f1, UNABBREV);
|
||||
f1 = spot::unabbreviate(f1, UNABBREV);
|
||||
f1.dump(std::cout) << std::endl;
|
||||
#endif
|
||||
#ifdef NENOFORM
|
||||
tmp = f1;
|
||||
f1 = spot::ltl::negative_normal_form(f1);
|
||||
f1 = spot::negative_normal_form(f1);
|
||||
f1.dump(std::cout) << std::endl;
|
||||
#endif
|
||||
#ifdef REDUC
|
||||
spot::ltl::ltl_simplifier_options opt(true, true, true,
|
||||
spot::ltl_simplifier_options opt(true, true, true,
|
||||
false, false);
|
||||
# ifdef EVENT_UNIV
|
||||
opt.favor_event_univ = true;
|
||||
# endif
|
||||
spot::ltl::ltl_simplifier simp(opt);
|
||||
spot::ltl_simplifier simp(opt);
|
||||
{
|
||||
spot::ltl::formula tmp;
|
||||
spot::formula tmp;
|
||||
tmp = f1;
|
||||
f1 = simp.simplify(f1);
|
||||
|
||||
|
|
@ -143,18 +143,18 @@ main(int argc, char** argv)
|
|||
{
|
||||
std::cerr
|
||||
<< "Source and simplified formulae are not equivalent!\n";
|
||||
spot::ltl::print_psl(std::cerr << "Simplified: ", f1) << '\n';
|
||||
spot::print_psl(std::cerr << "Simplified: ", f1) << '\n';
|
||||
exit_code = 1;
|
||||
}
|
||||
}
|
||||
f1.dump(std::cout) << std::endl;
|
||||
#endif
|
||||
#ifdef REDUC_TAU
|
||||
spot::ltl::ltl_simplifier_options opt(false, false, false,
|
||||
spot::ltl_simplifier_options opt(false, false, false,
|
||||
true, false);
|
||||
spot::ltl::ltl_simplifier simp(opt);
|
||||
spot::ltl_simplifier simp(opt);
|
||||
{
|
||||
spot::ltl::formula tmp;
|
||||
spot::formula tmp;
|
||||
tmp = f1;
|
||||
f1 = simp.simplify(f1);
|
||||
|
||||
|
|
@ -162,18 +162,18 @@ main(int argc, char** argv)
|
|||
{
|
||||
std::cerr
|
||||
<< "Source and simplified formulae are not equivalent!\n";
|
||||
spot::ltl::print_psl(std::cerr << "Simplified: ", f1) << '\n';
|
||||
spot::print_psl(std::cerr << "Simplified: ", f1) << '\n';
|
||||
exit_code = 1;
|
||||
}
|
||||
}
|
||||
f1.dump(std::cout) << std::endl;
|
||||
#endif
|
||||
#ifdef REDUC_TAUSTR
|
||||
spot::ltl::ltl_simplifier_options opt(false, false, false,
|
||||
spot::ltl_simplifier_options opt(false, false, false,
|
||||
true, true);
|
||||
spot::ltl::ltl_simplifier simp(opt);
|
||||
spot::ltl_simplifier simp(opt);
|
||||
{
|
||||
spot::ltl::formula tmp;
|
||||
spot::formula tmp;
|
||||
tmp = f1;
|
||||
f1 = simp.simplify(f1);
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ main(int argc, char** argv)
|
|||
{
|
||||
std::cerr
|
||||
<< "Source and simplified formulae are not equivalent!\n";
|
||||
spot::ltl::print_psl(std::cerr << "Simplified: ", f1) << '\n';
|
||||
spot::print_psl(std::cerr << "Simplified: ", f1) << '\n';
|
||||
exit_code = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -191,7 +191,7 @@ main(int argc, char** argv)
|
|||
exit_code |= f1 != f2;
|
||||
|
||||
#if (!defined(REDUC) && !defined(REDUC_TAU) && !defined(REDUC_TAUSTR))
|
||||
spot::ltl::ltl_simplifier simp;
|
||||
spot::ltl_simplifier simp;
|
||||
#endif
|
||||
|
||||
if (!simp.are_equivalent(f1, f2))
|
||||
|
|
@ -215,6 +215,6 @@ main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ checked_main(int argc, char** argv)
|
|||
bool nra2nba = false;
|
||||
bool scc_filter = false;
|
||||
bool simpltl = false;
|
||||
spot::ltl::ltl_simplifier_options redopt(false, false, false, false,
|
||||
spot::ltl_simplifier_options redopt(false, false, false, false,
|
||||
false, false, false);
|
||||
bool simpcache_stats = false;
|
||||
bool scc_filter_all = false;
|
||||
|
|
@ -363,8 +363,8 @@ checked_main(int argc, char** argv)
|
|||
bool opt_stutterize = false;
|
||||
const char* opt_never = nullptr;
|
||||
const char* hoa_opt = nullptr;
|
||||
auto& env = spot::ltl::default_environment::instance();
|
||||
spot::ltl::atomic_prop_set* unobservables = nullptr;
|
||||
auto& env = spot::default_environment::instance();
|
||||
spot::atomic_prop_set* unobservables = nullptr;
|
||||
spot::twa_ptr system_aut = nullptr;
|
||||
auto dict = spot::make_bdd_dict();
|
||||
spot::timer_map tm;
|
||||
|
|
@ -790,7 +790,7 @@ checked_main(int argc, char** argv)
|
|||
}
|
||||
else if (!strncmp(argv[formula_index], "-U", 2))
|
||||
{
|
||||
unobservables = new spot::ltl::atomic_prop_set;
|
||||
unobservables = new spot::atomic_prop_set;
|
||||
translation = TransFM;
|
||||
// Parse -U's argument.
|
||||
const char* tok = strtok(argv[formula_index] + 2, ", \t;");
|
||||
|
|
@ -923,7 +923,7 @@ checked_main(int argc, char** argv)
|
|||
input = argv[formula_index];
|
||||
}
|
||||
|
||||
spot::ltl::formula f = nullptr;
|
||||
spot::formula f = nullptr;
|
||||
if (!from_file) // Reading a formula, not reading an automaton from a file.
|
||||
{
|
||||
switch (translation)
|
||||
|
|
@ -932,11 +932,11 @@ checked_main(int argc, char** argv)
|
|||
case TransTAA:
|
||||
case TransCompo:
|
||||
{
|
||||
spot::ltl::parse_error_list pel;
|
||||
spot::parse_error_list pel;
|
||||
tm.start("parsing formula");
|
||||
f = spot::ltl::parse_infix_psl(input, pel, env, debug_opt);
|
||||
f = spot::parse_infix_psl(input, pel, env, debug_opt);
|
||||
tm.stop("parsing formula");
|
||||
exit_code = spot::ltl::format_parse_errors(std::cerr, input, pel);
|
||||
exit_code = spot::format_parse_errors(std::cerr, input, pel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -964,14 +964,14 @@ checked_main(int argc, char** argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
spot::ltl::ltl_simplifier* simp = nullptr;
|
||||
spot::ltl_simplifier* simp = nullptr;
|
||||
if (simpltl)
|
||||
simp = new spot::ltl::ltl_simplifier(redopt, dict);
|
||||
simp = new spot::ltl_simplifier(redopt, dict);
|
||||
|
||||
if (simp)
|
||||
{
|
||||
tm.start("reducing formula");
|
||||
spot::ltl::formula t = simp->simplify(f);
|
||||
spot::formula t = simp->simplify(f);
|
||||
tm.stop("reducing formula");
|
||||
f = t;
|
||||
if (display_reduced_form)
|
||||
|
|
@ -1659,6 +1659,6 @@ int
|
|||
main(int argc, char** argv)
|
||||
{
|
||||
int exit_code = checked_main(argc, argv);
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return exit_code;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,13 +58,13 @@ main(int argc, char **argv)
|
|||
std::getline(ss, form, ',');
|
||||
std::getline(ss, expected);
|
||||
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(form, p1);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, form, p1))
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_psl(form, p1);
|
||||
if (spot::format_parse_errors(std::cerr, form, p1))
|
||||
return 2;
|
||||
|
||||
std::ostringstream so;
|
||||
spot::ltl::print_formula_props(so, f1, true);
|
||||
spot::print_formula_props(so, f1, true);
|
||||
auto sost = so.str();
|
||||
std::cout << form << ',' << sost << '\n';
|
||||
if (sost != expected)
|
||||
|
|
@ -74,6 +74,6 @@ main(int argc, char **argv)
|
|||
return 2;
|
||||
}
|
||||
}
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,18 +45,18 @@ main(int argc, char **argv)
|
|||
}
|
||||
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(argv[1], p1);
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_psl(argv[1], p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[1], p1))
|
||||
if (spot::format_parse_errors(std::cerr, argv[1], p1))
|
||||
return 2;
|
||||
|
||||
if (boolone)
|
||||
std::cout << spot::ltl::length_boolone(f1) << std::endl;
|
||||
std::cout << spot::length_boolone(f1) << std::endl;
|
||||
else
|
||||
std::cout << spot::ltl::length(f1) << std::endl;
|
||||
std::cout << spot::length(f1) << std::endl;
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,18 +44,18 @@ main(int argc, char** argv)
|
|||
syntax(argv[0]);
|
||||
|
||||
{
|
||||
spot::ltl::environment& env(spot::ltl::default_environment::instance());
|
||||
spot::environment& env(spot::default_environment::instance());
|
||||
|
||||
spot::ltl::parse_error_list pel1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(argv[1], pel1, env);
|
||||
spot::parse_error_list pel1;
|
||||
auto f1 = spot::parse_infix_psl(argv[1], pel1, env);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[1], pel1))
|
||||
if (spot::format_parse_errors(std::cerr, argv[1], pel1))
|
||||
return 2;
|
||||
|
||||
spot::ltl::parse_error_list pel2;
|
||||
auto f2 = spot::ltl::parse_infix_psl(argv[2], pel2, env);
|
||||
spot::parse_error_list pel2;
|
||||
auto f2 = spot::parse_infix_psl(argv[2], pel2, env);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[2], pel2))
|
||||
if (spot::format_parse_errors(std::cerr, argv[2], pel2))
|
||||
return 2;
|
||||
|
||||
auto dict = spot::make_bdd_dict();
|
||||
|
|
@ -65,6 +65,6 @@ main(int argc, char** argv)
|
|||
spot::print_dot(std::cout, product(a1, a2));
|
||||
}
|
||||
}
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return exit_code;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,29 +38,29 @@ main(int argc, char **argv)
|
|||
syntax(argv[0]);
|
||||
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(argv[1], p1);
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_psl(argv[1], p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[1], p1))
|
||||
if (spot::format_parse_errors(std::cerr, argv[1], p1))
|
||||
return 2;
|
||||
|
||||
spot::ltl::relabeling_map* m = new spot::ltl::relabeling_map;
|
||||
auto f2 = spot::ltl::relabel_bse(f1, spot::ltl::Pnn, m);
|
||||
spot::ltl::print_psl(std::cout, f2) << '\n';
|
||||
spot::relabeling_map* m = new spot::relabeling_map;
|
||||
auto f2 = spot::relabel_bse(f1, spot::Pnn, m);
|
||||
spot::print_psl(std::cout, f2) << '\n';
|
||||
|
||||
|
||||
typedef std::map<std::string, std::string> map_t;
|
||||
map_t sorted_map;
|
||||
for (spot::ltl::relabeling_map::const_iterator i = m->begin();
|
||||
for (spot::relabeling_map::const_iterator i = m->begin();
|
||||
i != m->end(); ++i)
|
||||
sorted_map[spot::ltl::str_psl(i->first)] =
|
||||
spot::ltl::str_psl(i->second);
|
||||
sorted_map[spot::str_psl(i->first)] =
|
||||
spot::str_psl(i->second);
|
||||
for (map_t::const_iterator i = sorted_map.begin();
|
||||
i != sorted_map.end(); ++i)
|
||||
std::cout << " " << i->first << " -> "
|
||||
<< i->second << '\n';
|
||||
delete m;
|
||||
}
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# Check that spot::ltl::parse succeed on valid input, and that
|
||||
# Check that spot::parse succeed on valid input, and that
|
||||
# dump and dotty will work with the resulting trees. Note that
|
||||
# this doesn't check that the tree is correct w.r.t. the formula.
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,6 @@ int main(int argc, char** argv)
|
|||
kripke_save_reachable(std::cout, k);
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return return_value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -486,9 +486,9 @@ print_ar_stats(ar_stats_type& ar_stats, const std::string& s)
|
|||
std::cout << std::setiosflags(old);
|
||||
}
|
||||
|
||||
spot::ltl::formula
|
||||
generate_formula(const spot::ltl::random_ltl& rl,
|
||||
spot::ltl::ltl_simplifier& simp,
|
||||
spot::formula
|
||||
generate_formula(const spot::random_ltl& rl,
|
||||
spot::ltl_simplifier& simp,
|
||||
int opt_f, int opt_s,
|
||||
int opt_l = 0, bool opt_u = false)
|
||||
{
|
||||
|
|
@ -498,7 +498,7 @@ generate_formula(const spot::ltl::random_ltl& rl,
|
|||
while (max_tries_u--)
|
||||
{
|
||||
spot::srand(opt_s++);
|
||||
spot::ltl::formula f;
|
||||
spot::formula f;
|
||||
int max_tries_l = 1000;
|
||||
while (max_tries_l--)
|
||||
{
|
||||
|
|
@ -506,12 +506,12 @@ generate_formula(const spot::ltl::random_ltl& rl,
|
|||
if (opt_l)
|
||||
{
|
||||
f = simp.simplify(f);
|
||||
if (spot::ltl::length(f) < opt_l)
|
||||
if (spot::length(f) < opt_l)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(spot::ltl::length(f) <= opt_f);
|
||||
assert(spot::length(f) <= opt_f);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -522,7 +522,7 @@ generate_formula(const spot::ltl::random_ltl& rl,
|
|||
<< "of size " << opt_l << " or more." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
std::string txt = spot::ltl::str_psl(f);
|
||||
std::string txt = spot::str_psl(f);
|
||||
if (!opt_u || unique.insert(txt).second)
|
||||
return f;
|
||||
}
|
||||
|
|
@ -576,12 +576,12 @@ main(int argc, char** argv)
|
|||
|
||||
spot::option_map options;
|
||||
|
||||
auto& env = spot::ltl::default_environment::instance();
|
||||
spot::ltl::atomic_prop_set* ap = new spot::ltl::atomic_prop_set;
|
||||
auto& env = spot::default_environment::instance();
|
||||
spot::atomic_prop_set* ap = new spot::atomic_prop_set;
|
||||
auto dict = spot::make_bdd_dict();
|
||||
|
||||
spot::ltl::ltl_simplifier_options simpopt(true, true, true, true, true);
|
||||
spot::ltl::ltl_simplifier simp(simpopt);
|
||||
spot::ltl_simplifier_options simpopt(true, true, true, true, true);
|
||||
spot::ltl_simplifier simp(simpopt);
|
||||
|
||||
if (argc <= 1)
|
||||
syntax(argv[0]);
|
||||
|
|
@ -788,7 +788,7 @@ main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
spot::ltl::random_ltl rl(ap);
|
||||
spot::random_ltl rl(ap);
|
||||
const char* tok = rl.parse_options(opt_p);
|
||||
if (tok)
|
||||
{
|
||||
|
|
@ -824,7 +824,7 @@ main(int argc, char** argv)
|
|||
spot::timer_map tm_ar;
|
||||
std::set<int> failed_seeds;
|
||||
int init_opt_ec = opt_ec;
|
||||
spot::ltl::atomic_prop_set* apf = new spot::ltl::atomic_prop_set;
|
||||
spot::atomic_prop_set* apf = new spot::atomic_prop_set;
|
||||
|
||||
if (opt_ec)
|
||||
{
|
||||
|
|
@ -847,7 +847,7 @@ main(int argc, char** argv)
|
|||
{
|
||||
if (opt_F)
|
||||
{
|
||||
spot::ltl::formula f =
|
||||
spot::formula f =
|
||||
generate_formula(rl, simp, opt_f, opt_ec_seed, opt_l, opt_u);
|
||||
if (!f)
|
||||
exit(1);
|
||||
|
|
@ -862,15 +862,15 @@ main(int argc, char** argv)
|
|||
break;
|
||||
else if (input == "")
|
||||
break;
|
||||
spot::ltl::parse_error_list pel;
|
||||
auto f = spot::ltl::parse_infix_psl(input, pel, env);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
|
||||
spot::parse_error_list pel;
|
||||
auto f = spot::parse_infix_psl(input, pel, env);
|
||||
if (spot::format_parse_errors(std::cerr, input, pel))
|
||||
{
|
||||
exit_code = 1;
|
||||
break;
|
||||
}
|
||||
formula = spot::ltl_to_tgba_fm(f, dict, true);
|
||||
auto* tmp = spot::ltl::atomic_prop_collect(f);
|
||||
auto* tmp = spot::atomic_prop_collect(f);
|
||||
for (auto i: *tmp)
|
||||
apf->insert(i);
|
||||
delete tmp;
|
||||
|
|
|
|||
|
|
@ -54,18 +54,18 @@ main(int argc, char** argv)
|
|||
}
|
||||
|
||||
{
|
||||
spot::ltl::environment& env(spot::ltl::default_environment::instance());
|
||||
spot::ltl::parse_error_list pel;
|
||||
auto f = spot::ltl::parse_infix_psl(argv[formula_index], pel, env, debug);
|
||||
spot::environment& env(spot::default_environment::instance());
|
||||
spot::parse_error_list pel;
|
||||
auto f = spot::parse_infix_psl(argv[formula_index], pel, env, debug);
|
||||
|
||||
exit_code =
|
||||
spot::ltl::format_parse_errors(std::cerr, argv[formula_index], pel);
|
||||
spot::format_parse_errors(std::cerr, argv[formula_index], pel);
|
||||
|
||||
|
||||
if (f)
|
||||
{
|
||||
#ifdef DOTTY
|
||||
spot::ltl::print_dot_psl(std::cout, f);
|
||||
spot::print_dot_psl(std::cout, f);
|
||||
#else
|
||||
f.dump(std::cout) << std::endl;
|
||||
#endif
|
||||
|
|
@ -76,6 +76,6 @@ main(int argc, char** argv)
|
|||
}
|
||||
|
||||
}
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return exit_code;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ main(int argc, char** argv)
|
|||
bool hidereduc = false;
|
||||
unsigned long sum_before = 0;
|
||||
unsigned long sum_after = 0;
|
||||
spot::ltl::ltl_simplifier_options o(false, false, false, false, false);
|
||||
spot::ltl_simplifier_options o(false, false, false, false, false);
|
||||
|
||||
if (argc < 3)
|
||||
syntax(argv[0]);
|
||||
|
|
@ -147,12 +147,12 @@ main(int argc, char** argv)
|
|||
int exit_code = 0;
|
||||
|
||||
{
|
||||
spot::ltl::ltl_simplifier* simp = new spot::ltl::ltl_simplifier(o);
|
||||
spot::ltl_simplifier* simp = new spot::ltl_simplifier(o);
|
||||
o.reduce_size_strictly = true;
|
||||
spot::ltl::ltl_simplifier* simp_size = new spot::ltl::ltl_simplifier(o);
|
||||
spot::ltl_simplifier* simp_size = new spot::ltl_simplifier(o);
|
||||
|
||||
spot::ltl::formula f1 = nullptr;
|
||||
spot::ltl::formula f2 = nullptr;
|
||||
spot::formula f1 = nullptr;
|
||||
spot::formula f2 = nullptr;
|
||||
|
||||
std::ifstream* fin = nullptr;
|
||||
|
||||
|
|
@ -178,16 +178,16 @@ main(int argc, char** argv)
|
|||
}
|
||||
while (input == "");
|
||||
|
||||
spot::ltl::parse_error_list p1;
|
||||
f1 = spot::ltl::parse_infix_psl(input, p1);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, input, p1))
|
||||
spot::parse_error_list p1;
|
||||
f1 = spot::parse_infix_psl(input, p1);
|
||||
if (spot::format_parse_errors(std::cerr, input, p1))
|
||||
return 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
f1 = spot::ltl::parse_infix_psl(argv[2], p1);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[2], p1))
|
||||
spot::parse_error_list p1;
|
||||
f1 = spot::parse_infix_psl(argv[2], p1);
|
||||
if (spot::format_parse_errors(std::cerr, argv[2], p1))
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
|
@ -199,23 +199,23 @@ main(int argc, char** argv)
|
|||
exit(2);
|
||||
}
|
||||
|
||||
spot::ltl::parse_error_list p2;
|
||||
f2 = spot::ltl::parse_infix_psl(argv[3], p2);
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[3], p2))
|
||||
spot::parse_error_list p2;
|
||||
f2 = spot::parse_infix_psl(argv[3], p2);
|
||||
if (spot::format_parse_errors(std::cerr, argv[3], p2))
|
||||
return 2;
|
||||
}
|
||||
|
||||
{
|
||||
spot::ltl::formula ftmp1;
|
||||
spot::formula ftmp1;
|
||||
|
||||
ftmp1 = f1;
|
||||
f1 = simp_size->negative_normal_form(f1, false);
|
||||
|
||||
int length_f1_before = spot::ltl::length(f1);
|
||||
std::string f1s_before = spot::ltl::str_psl(f1);
|
||||
int length_f1_before = spot::length(f1);
|
||||
std::string f1s_before = spot::str_psl(f1);
|
||||
std::string f1l;
|
||||
|
||||
spot::ltl::formula input_f = f1;
|
||||
spot::formula input_f = f1;
|
||||
f1 = simp_size->simplify(input_f);
|
||||
if (!simp_size->are_equivalent(input_f, f1))
|
||||
{
|
||||
|
|
@ -226,8 +226,8 @@ main(int argc, char** argv)
|
|||
}
|
||||
else
|
||||
{
|
||||
spot::ltl::formula maybe_larger = simp->simplify(input_f);
|
||||
f1l = spot::ltl::str_psl(maybe_larger);
|
||||
spot::formula maybe_larger = simp->simplify(input_f);
|
||||
f1l = spot::str_psl(maybe_larger);
|
||||
if (!simp->are_equivalent(input_f, maybe_larger))
|
||||
{
|
||||
std::cerr << "Incorrect reduction (reduce_size_strictly=0) from `"
|
||||
|
|
@ -236,15 +236,15 @@ main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
int length_f1_after = spot::ltl::length(f1);
|
||||
std::string f1s_after = spot::ltl::str_psl(f1);
|
||||
int length_f1_after = spot::length(f1);
|
||||
std::string f1s_after = spot::str_psl(f1);
|
||||
|
||||
std::string f2s = "";
|
||||
if (f2)
|
||||
{
|
||||
ftmp1 = f2;
|
||||
f2 = simp_size->negative_normal_form(f2, false);
|
||||
f2s = spot::ltl::str_psl(f2);
|
||||
f2s = spot::str_psl(f2);
|
||||
}
|
||||
|
||||
sum_before += length_f1_before;
|
||||
|
|
@ -308,6 +308,6 @@ main(int argc, char** argv)
|
|||
}
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return exit_code;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,25 +45,25 @@ main(int argc, char** argv)
|
|||
int exit_return = 0;
|
||||
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto ftmp1 = spot::ltl::parse_infix_psl(argv[2], p1);
|
||||
spot::parse_error_list p1;
|
||||
auto ftmp1 = spot::parse_infix_psl(argv[2], p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[2], p1))
|
||||
if (spot::format_parse_errors(std::cerr, argv[2], p1))
|
||||
return 2;
|
||||
|
||||
spot::ltl::parse_error_list p2;
|
||||
auto ftmp2 = spot::ltl::parse_infix_psl(argv[3], p2);
|
||||
spot::parse_error_list p2;
|
||||
auto ftmp2 = spot::parse_infix_psl(argv[3], p2);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[3], p2))
|
||||
if (spot::format_parse_errors(std::cerr, argv[3], p2))
|
||||
return 2;
|
||||
|
||||
spot::ltl::formula f1 = spot::ltl::negative_normal_form(ftmp1);
|
||||
spot::ltl::formula f2 = spot::ltl::negative_normal_form(ftmp2);
|
||||
spot::formula f1 = spot::negative_normal_form(ftmp1);
|
||||
spot::formula f2 = spot::negative_normal_form(ftmp2);
|
||||
|
||||
std::string f1s = spot::ltl::str_psl(f1);
|
||||
std::string f2s = spot::ltl::str_psl(f2);
|
||||
std::string f1s = spot::str_psl(f1);
|
||||
std::string f2s = spot::str_psl(f2);
|
||||
|
||||
spot::ltl::ltl_simplifier* c = new spot::ltl::ltl_simplifier;
|
||||
spot::ltl_simplifier* c = new spot::ltl_simplifier;
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
|
|
@ -102,6 +102,6 @@ main(int argc, char** argv)
|
|||
|
||||
delete c;
|
||||
}
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return exit_return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ int
|
|||
main()
|
||||
{
|
||||
{
|
||||
spot::ltl::default_environment& e =
|
||||
spot::ltl::default_environment::instance();
|
||||
spot::default_environment& e =
|
||||
spot::default_environment::instance();
|
||||
auto a = spot::make_taa_tgba_string(spot::make_bdd_dict());
|
||||
|
||||
typedef spot::taa_tgba::transition trans;
|
||||
|
|
@ -48,6 +48,6 @@ main()
|
|||
spot::print_dot(std::cout, a);
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,21 +40,21 @@ main(int argc, char **argv)
|
|||
syntax(argv[0]);
|
||||
|
||||
{
|
||||
spot::ltl::parse_error_list p1;
|
||||
auto f1 = spot::ltl::parse_infix_psl(argv[1], p1);
|
||||
spot::parse_error_list p1;
|
||||
auto f1 = spot::parse_infix_psl(argv[1], p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, argv[1], p1))
|
||||
if (spot::format_parse_errors(std::cerr, argv[1], p1))
|
||||
return 2;
|
||||
|
||||
// The string generated from an abstract tree should be parsable
|
||||
// again.
|
||||
|
||||
std::string f1s = spot::ltl::str_psl(f1);
|
||||
std::string f1s = spot::str_psl(f1);
|
||||
std::cout << f1s << '\n';
|
||||
|
||||
auto f2 = spot::ltl::parse_infix_psl(f1s, p1);
|
||||
auto f2 = spot::parse_infix_psl(f1s, p1);
|
||||
|
||||
if (spot::ltl::format_parse_errors(std::cerr, f1s, p1))
|
||||
if (spot::format_parse_errors(std::cerr, f1s, p1))
|
||||
return 2;
|
||||
|
||||
// This second abstract tree should be equal to the first.
|
||||
|
|
@ -64,13 +64,13 @@ main(int argc, char **argv)
|
|||
|
||||
// It should also map to the same string.
|
||||
|
||||
std::string f2s = spot::ltl::str_psl(f2);
|
||||
std::string f2s = spot::str_psl(f2);
|
||||
std::cout << f2s << '\n';
|
||||
|
||||
if (f2s != f1s)
|
||||
return 1;
|
||||
}
|
||||
|
||||
assert(spot::ltl::fnode::instances_check());
|
||||
assert(spot::fnode::instances_check());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
# Check for spot::ltl::tostring.
|
||||
# Check for spot::tostring.
|
||||
|
||||
. ./defs || exit 1
|
||||
|
||||
|
|
|
|||
|
|
@ -26,43 +26,40 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
atomic_prop_set create_atomic_prop_set(unsigned n)
|
||||
{
|
||||
atomic_prop_set create_atomic_prop_set(unsigned n)
|
||||
{
|
||||
atomic_prop_set res;
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
std::ostringstream p;
|
||||
p << 'p' << i;
|
||||
res.insert(formula::ap(p.str()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
atomic_prop_set res;
|
||||
for (unsigned i = 0; i < n; ++i)
|
||||
{
|
||||
std::ostringstream p;
|
||||
p << 'p' << i;
|
||||
res.insert(formula::ap(p.str()));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
atomic_prop_set*
|
||||
atomic_prop_collect(formula f, atomic_prop_set* s)
|
||||
{
|
||||
if (!s)
|
||||
s = new atomic_prop_set;
|
||||
f.traverse([&](const formula& f)
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
s->insert(f);
|
||||
return false;
|
||||
});
|
||||
return s;
|
||||
}
|
||||
atomic_prop_set*
|
||||
atomic_prop_collect(formula f, atomic_prop_set* s)
|
||||
{
|
||||
if (!s)
|
||||
s = new atomic_prop_set;
|
||||
f.traverse([&](const formula& f)
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
s->insert(f);
|
||||
return false;
|
||||
});
|
||||
return s;
|
||||
}
|
||||
|
||||
bdd
|
||||
atomic_prop_collect_as_bdd(formula f, const twa_ptr& a)
|
||||
{
|
||||
spot::ltl::atomic_prop_set aps;
|
||||
atomic_prop_collect(f, &aps);
|
||||
bdd res = bddtrue;
|
||||
for (auto f: aps)
|
||||
res &= bdd_ithvar(a->register_ap(f));
|
||||
return res;
|
||||
}
|
||||
bdd
|
||||
atomic_prop_collect_as_bdd(formula f, const twa_ptr& a)
|
||||
{
|
||||
spot::atomic_prop_set aps;
|
||||
atomic_prop_collect(f, &aps);
|
||||
bdd res = bddtrue;
|
||||
for (auto f: aps)
|
||||
res &= bdd_ithvar(a->register_ap(f));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,38 +29,35 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \addtogroup ltl_misc
|
||||
/// @{
|
||||
/// \addtogroup ltl_misc
|
||||
/// @{
|
||||
|
||||
/// Set of atomic propositions.
|
||||
typedef std::set<formula> atomic_prop_set;
|
||||
/// Set of atomic propositions.
|
||||
typedef std::set<formula> atomic_prop_set;
|
||||
|
||||
/// \brief construct an atomic_prop_set with n propositions
|
||||
SPOT_API
|
||||
atomic_prop_set create_atomic_prop_set(unsigned n);
|
||||
/// \brief construct an atomic_prop_set with n propositions
|
||||
SPOT_API
|
||||
atomic_prop_set create_atomic_prop_set(unsigned n);
|
||||
|
||||
/// \brief Return the set of atomic propositions occurring in a formula.
|
||||
///
|
||||
/// \param f the formula to inspect
|
||||
/// \param s an existing set to fill with atomic_propositions discovered,
|
||||
/// or 0 if the set should be allocated by the function.
|
||||
/// \return A pointer to the supplied set, \c s, augmented with
|
||||
/// atomic propositions occurring in \c f; or a newly allocated
|
||||
/// set containing all these atomic propositions if \c s is 0.
|
||||
SPOT_API atomic_prop_set*
|
||||
atomic_prop_collect(formula f, atomic_prop_set* s = nullptr);
|
||||
/// \brief Return the set of atomic propositions occurring in a formula.
|
||||
///
|
||||
/// \param f the formula to inspect
|
||||
/// \param s an existing set to fill with atomic_propositions discovered,
|
||||
/// or 0 if the set should be allocated by the function.
|
||||
/// \return A pointer to the supplied set, \c s, augmented with
|
||||
/// atomic propositions occurring in \c f; or a newly allocated
|
||||
/// set containing all these atomic propositions if \c s is 0.
|
||||
SPOT_API atomic_prop_set*
|
||||
atomic_prop_collect(formula f, atomic_prop_set* s = nullptr);
|
||||
|
||||
/// \brief Return the set of atomic propositions occurring in a
|
||||
/// formula, as a BDD.
|
||||
///
|
||||
/// \param f the formula to inspect
|
||||
/// \param a that automaton that should register the BDD variables used.
|
||||
/// \return A conjunction the atomic propositions.
|
||||
SPOT_API bdd
|
||||
atomic_prop_collect_as_bdd(formula f, const twa_ptr& a);
|
||||
/// \brief Return the set of atomic propositions occurring in a
|
||||
/// formula, as a BDD.
|
||||
///
|
||||
/// \param f the formula to inspect
|
||||
/// \param a that automaton that should register the BDD variables used.
|
||||
/// \return A conjunction the atomic propositions.
|
||||
SPOT_API bdd
|
||||
atomic_prop_collect_as_bdd(formula f, const twa_ptr& a);
|
||||
|
||||
/// @}
|
||||
}
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,114 +27,110 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
|
||||
language_containment_checker::language_containment_checker
|
||||
(const bdd_dict_ptr& dict, bool exprop, bool symb_merge,
|
||||
bool branching_postponement, bool fair_loop_approx)
|
||||
: dict_(dict), exprop_(exprop), symb_merge_(symb_merge),
|
||||
language_containment_checker::language_containment_checker
|
||||
(const bdd_dict_ptr& dict, bool exprop, bool symb_merge,
|
||||
bool branching_postponement, bool fair_loop_approx)
|
||||
: dict_(dict), exprop_(exprop), symb_merge_(symb_merge),
|
||||
branching_postponement_(branching_postponement),
|
||||
fair_loop_approx_(fair_loop_approx)
|
||||
{
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
language_containment_checker::~language_containment_checker()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
language_containment_checker::~language_containment_checker()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void
|
||||
language_containment_checker::clear()
|
||||
{
|
||||
translated_.clear();
|
||||
}
|
||||
void
|
||||
language_containment_checker::clear()
|
||||
{
|
||||
translated_.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
language_containment_checker::incompatible_(record_* l, record_* g)
|
||||
{
|
||||
record_::incomp_map::const_iterator i = l->incompatible.find(g);
|
||||
if (i != l->incompatible.end())
|
||||
return i->second;
|
||||
bool
|
||||
language_containment_checker::incompatible_(record_* l, record_* g)
|
||||
{
|
||||
record_::incomp_map::const_iterator i = l->incompatible.find(g);
|
||||
if (i != l->incompatible.end())
|
||||
return i->second;
|
||||
|
||||
bool res = product(l->translation, g->translation)->is_empty();
|
||||
l->incompatible[g] = res;
|
||||
g->incompatible[l] = res;
|
||||
return res;
|
||||
}
|
||||
bool res = product(l->translation, g->translation)->is_empty();
|
||||
l->incompatible[g] = res;
|
||||
g->incompatible[l] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
// Check whether L(l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::contained(formula l,
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return true;
|
||||
record_* rl = register_formula_(l);
|
||||
record_* rng = register_formula_(formula::Not(g));
|
||||
return incompatible_(rl, rng);
|
||||
}
|
||||
// Check whether L(l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::contained(formula l,
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return true;
|
||||
record_* rl = register_formula_(l);
|
||||
record_* rng = register_formula_(formula::Not(g));
|
||||
return incompatible_(rl, rng);
|
||||
}
|
||||
|
||||
// Check whether L(!l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::neg_contained(formula l,
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
formula nl = formula::Not(l);
|
||||
record_* rnl = register_formula_(nl);
|
||||
record_* rng = register_formula_(formula::Not(g));
|
||||
if (nl == g)
|
||||
return true;
|
||||
return incompatible_(rnl, rng);
|
||||
}
|
||||
// Check whether L(!l) is a subset of L(g).
|
||||
bool
|
||||
language_containment_checker::neg_contained(formula l,
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
formula nl = formula::Not(l);
|
||||
record_* rnl = register_formula_(nl);
|
||||
record_* rng = register_formula_(formula::Not(g));
|
||||
if (nl == g)
|
||||
return true;
|
||||
return incompatible_(rnl, rng);
|
||||
}
|
||||
|
||||
// Check whether L(l) is a subset of L(!g).
|
||||
bool
|
||||
language_containment_checker::contained_neg(formula l,
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
record_* rl = register_formula_(l);
|
||||
record_* rg = register_formula_(g);
|
||||
return incompatible_(rl, rg);
|
||||
}
|
||||
// Check whether L(l) is a subset of L(!g).
|
||||
bool
|
||||
language_containment_checker::contained_neg(formula l,
|
||||
formula g)
|
||||
{
|
||||
if (l == g)
|
||||
return false;
|
||||
record_* rl = register_formula_(l);
|
||||
record_* rg = register_formula_(g);
|
||||
return incompatible_(rl, rg);
|
||||
}
|
||||
|
||||
// Check whether L(l) = L(g).
|
||||
bool
|
||||
language_containment_checker::equal(formula l, formula g)
|
||||
{
|
||||
return contained(l, g) && contained(g, l);
|
||||
}
|
||||
// Check whether L(l) = L(g).
|
||||
bool
|
||||
language_containment_checker::equal(formula l, formula g)
|
||||
{
|
||||
return contained(l, g) && contained(g, l);
|
||||
}
|
||||
|
||||
language_containment_checker::record_*
|
||||
language_containment_checker::register_formula_(formula f)
|
||||
{
|
||||
trans_map::iterator i = translated_.find(f);
|
||||
if (i != translated_.end())
|
||||
return &i->second;
|
||||
language_containment_checker::record_*
|
||||
language_containment_checker::register_formula_(formula f)
|
||||
{
|
||||
trans_map::iterator i = translated_.find(f);
|
||||
if (i != translated_.end())
|
||||
return &i->second;
|
||||
|
||||
auto e = ltl_to_tgba_fm(f, dict_, exprop_, symb_merge_,
|
||||
branching_postponement_, fair_loop_approx_);
|
||||
record_& r = translated_[f];
|
||||
r.translation = e;
|
||||
return &r;
|
||||
}
|
||||
auto e = ltl_to_tgba_fm(f, dict_, exprop_, symb_merge_,
|
||||
branching_postponement_, fair_loop_approx_);
|
||||
record_& r = translated_[f];
|
||||
r.translation = e;
|
||||
return &r;
|
||||
}
|
||||
|
||||
|
||||
formula
|
||||
reduce_tau03(formula f, bool stronger)
|
||||
{
|
||||
if (!f.is_psl_formula())
|
||||
return f;
|
||||
formula
|
||||
reduce_tau03(formula f, bool stronger)
|
||||
{
|
||||
if (!f.is_psl_formula())
|
||||
return f;
|
||||
|
||||
ltl_simplifier_options opt(false, false, false,
|
||||
true, stronger);
|
||||
ltl_simplifier simpl(opt);
|
||||
return simpl.simplify(f);
|
||||
}
|
||||
ltl_simplifier_options opt(false, false, false,
|
||||
true, stronger);
|
||||
ltl_simplifier simpl(opt);
|
||||
return simpl.simplify(f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,54 +29,51 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
/// Check containment between LTL formulae.
|
||||
class SPOT_API language_containment_checker
|
||||
{
|
||||
/// Check containment between LTL formulae.
|
||||
class SPOT_API language_containment_checker
|
||||
struct record_
|
||||
{
|
||||
struct record_
|
||||
{
|
||||
const_twa_graph_ptr translation;
|
||||
typedef std::map<const record_*, bool> incomp_map;
|
||||
incomp_map incompatible;
|
||||
};
|
||||
typedef std::unordered_map<formula, record_> trans_map;
|
||||
public:
|
||||
/// This class uses spot::ltl_to_tgba_fm to translate LTL
|
||||
/// formulae. See that function for the meaning of these options.
|
||||
language_containment_checker(const bdd_dict_ptr& dict, bool exprop,
|
||||
bool symb_merge,
|
||||
bool branching_postponement,
|
||||
bool fair_loop_approx);
|
||||
|
||||
~language_containment_checker();
|
||||
|
||||
/// Clear the cache.
|
||||
void clear();
|
||||
|
||||
/// Check whether L(l) is a subset of L(g).
|
||||
bool contained(formula l, formula g);
|
||||
/// Check whether L(!l) is a subset of L(g).
|
||||
bool neg_contained(formula l, formula g);
|
||||
/// Check whether L(l) is a subset of L(!g).
|
||||
bool contained_neg(formula l, formula g);
|
||||
|
||||
/// Check whether L(l) = L(g).
|
||||
bool equal(formula l, formula g);
|
||||
|
||||
protected:
|
||||
bool incompatible_(record_* l, record_* g);
|
||||
|
||||
record_* register_formula_(formula f);
|
||||
|
||||
/* Translation options */
|
||||
bdd_dict_ptr dict_;
|
||||
bool exprop_;
|
||||
bool symb_merge_;
|
||||
bool branching_postponement_;
|
||||
bool fair_loop_approx_;
|
||||
/* Translation Maps */
|
||||
trans_map translated_;
|
||||
const_twa_graph_ptr translation;
|
||||
typedef std::map<const record_*, bool> incomp_map;
|
||||
incomp_map incompatible;
|
||||
};
|
||||
}
|
||||
typedef std::unordered_map<formula, record_> trans_map;
|
||||
public:
|
||||
/// This class uses spot::ltl_to_tgba_fm to translate LTL
|
||||
/// formulae. See that function for the meaning of these options.
|
||||
language_containment_checker(const bdd_dict_ptr& dict, bool exprop,
|
||||
bool symb_merge,
|
||||
bool branching_postponement,
|
||||
bool fair_loop_approx);
|
||||
|
||||
~language_containment_checker();
|
||||
|
||||
/// Clear the cache.
|
||||
void clear();
|
||||
|
||||
/// Check whether L(l) is a subset of L(g).
|
||||
bool contained(formula l, formula g);
|
||||
/// Check whether L(!l) is a subset of L(g).
|
||||
bool neg_contained(formula l, formula g);
|
||||
/// Check whether L(l) is a subset of L(!g).
|
||||
bool contained_neg(formula l, formula g);
|
||||
|
||||
/// Check whether L(l) = L(g).
|
||||
bool equal(formula l, formula g);
|
||||
|
||||
protected:
|
||||
bool incompatible_(record_* l, record_* g);
|
||||
|
||||
record_* register_formula_(formula f);
|
||||
|
||||
/* Translation options */
|
||||
bdd_dict_ptr dict_;
|
||||
bool exprop_;
|
||||
bool symb_merge_;
|
||||
bool branching_postponement_;
|
||||
bool fair_loop_approx_;
|
||||
/* Translation Maps */
|
||||
trans_map translated_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,42 +24,38 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
declarative_environment::declarative_environment()
|
||||
{
|
||||
}
|
||||
|
||||
declarative_environment::declarative_environment()
|
||||
{
|
||||
}
|
||||
bool
|
||||
declarative_environment::declare(const std::string& prop_str)
|
||||
{
|
||||
if (props_.find(prop_str) != props_.end())
|
||||
return false;
|
||||
props_[prop_str] = formula::ap(prop_str);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
declarative_environment::declare(const std::string& prop_str)
|
||||
{
|
||||
if (props_.find(prop_str) != props_.end())
|
||||
return false;
|
||||
props_[prop_str] = formula::ap(prop_str);
|
||||
return true;
|
||||
}
|
||||
formula
|
||||
declarative_environment::require(const std::string& prop_str)
|
||||
{
|
||||
prop_map::iterator i = props_.find(prop_str);
|
||||
if (i == props_.end())
|
||||
return nullptr;
|
||||
return i->second;
|
||||
}
|
||||
|
||||
formula
|
||||
declarative_environment::require(const std::string& prop_str)
|
||||
{
|
||||
prop_map::iterator i = props_.find(prop_str);
|
||||
if (i == props_.end())
|
||||
return nullptr;
|
||||
return i->second;
|
||||
}
|
||||
const std::string&
|
||||
declarative_environment::name() const
|
||||
{
|
||||
static std::string name("declarative environment");
|
||||
return name;
|
||||
}
|
||||
|
||||
const std::string&
|
||||
declarative_environment::name() const
|
||||
{
|
||||
static std::string name("declarative environment");
|
||||
return name;
|
||||
}
|
||||
|
||||
const declarative_environment::prop_map&
|
||||
declarative_environment::get_prop_map() const
|
||||
{
|
||||
return props_;
|
||||
}
|
||||
const declarative_environment::prop_map&
|
||||
declarative_environment::get_prop_map() const
|
||||
{
|
||||
return props_;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,36 +29,32 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
/// \ingroup ltl_environment
|
||||
/// \brief A declarative environment.
|
||||
///
|
||||
/// This environment recognizes all atomic propositions
|
||||
/// that have been previously declared. It will reject other.
|
||||
class SPOT_API declarative_environment : public environment
|
||||
{
|
||||
public:
|
||||
declarative_environment();
|
||||
~declarative_environment() = default;
|
||||
|
||||
/// \ingroup ltl_environment
|
||||
/// \brief A declarative environment.
|
||||
///
|
||||
/// This environment recognizes all atomic propositions
|
||||
/// that have been previously declared. It will reject other.
|
||||
class SPOT_API declarative_environment : public environment
|
||||
{
|
||||
public:
|
||||
declarative_environment();
|
||||
~declarative_environment() = default;
|
||||
/// Declare an atomic proposition. Return false iff the
|
||||
/// proposition was already declared.
|
||||
bool declare(const std::string& prop_str);
|
||||
|
||||
/// Declare an atomic proposition. Return false iff the
|
||||
/// proposition was already declared.
|
||||
bool declare(const std::string& prop_str);
|
||||
virtual formula require(const std::string& prop_str);
|
||||
|
||||
virtual formula require(const std::string& prop_str);
|
||||
/// Get the name of the environment.
|
||||
virtual const std::string& name() const;
|
||||
|
||||
/// Get the name of the environment.
|
||||
virtual const std::string& name() const;
|
||||
typedef std::map<const std::string, formula> prop_map;
|
||||
|
||||
typedef std::map<const std::string, formula> prop_map;
|
||||
/// Get the map of atomic proposition known to this environment.
|
||||
const prop_map& get_prop_map() const;
|
||||
|
||||
/// Get the map of atomic proposition known to this environment.
|
||||
const prop_map& get_prop_map() const;
|
||||
|
||||
private:
|
||||
prop_map props_;
|
||||
};
|
||||
}
|
||||
private:
|
||||
prop_map props_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,36 +24,31 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
default_environment::~default_environment()
|
||||
{
|
||||
}
|
||||
|
||||
default_environment::~default_environment()
|
||||
{
|
||||
}
|
||||
formula
|
||||
default_environment::require(const std::string& s)
|
||||
{
|
||||
return formula::ap(s);
|
||||
}
|
||||
|
||||
formula
|
||||
default_environment::require(const std::string& s)
|
||||
{
|
||||
return formula::ap(s);
|
||||
}
|
||||
const std::string&
|
||||
default_environment::name() const
|
||||
{
|
||||
static std::string name("default environment");
|
||||
return name;
|
||||
}
|
||||
|
||||
const std::string&
|
||||
default_environment::name() const
|
||||
{
|
||||
static std::string name("default environment");
|
||||
return name;
|
||||
}
|
||||
|
||||
default_environment::default_environment()
|
||||
{
|
||||
}
|
||||
|
||||
default_environment&
|
||||
default_environment::instance()
|
||||
{
|
||||
static default_environment* singleton = new default_environment();
|
||||
return *singleton;
|
||||
}
|
||||
default_environment::default_environment()
|
||||
{
|
||||
}
|
||||
|
||||
default_environment&
|
||||
default_environment::instance()
|
||||
{
|
||||
static default_environment* singleton = new default_environment();
|
||||
return *singleton;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,27 +27,23 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
/// \ingroup ltl_environment
|
||||
/// \brief A laxist environment.
|
||||
///
|
||||
/// This environment recognizes all atomic propositions.
|
||||
///
|
||||
/// This is a singleton. Use default_environment::instance()
|
||||
/// to obtain the instance.
|
||||
class SPOT_API default_environment final: public environment
|
||||
{
|
||||
public:
|
||||
virtual ~default_environment();
|
||||
virtual formula require(const std::string& prop_str);
|
||||
virtual const std::string& name() const;
|
||||
|
||||
/// \ingroup ltl_environment
|
||||
/// \brief A laxist environment.
|
||||
///
|
||||
/// This environment recognizes all atomic propositions.
|
||||
///
|
||||
/// This is a singleton. Use default_environment::instance()
|
||||
/// to obtain the instance.
|
||||
class SPOT_API default_environment final: public environment
|
||||
{
|
||||
public:
|
||||
virtual ~default_environment();
|
||||
virtual formula require(const std::string& prop_str);
|
||||
virtual const std::string& name() const;
|
||||
|
||||
/// Get the sole instance of spot::ltl::default_environment.
|
||||
static default_environment& instance();
|
||||
protected:
|
||||
default_environment();
|
||||
};
|
||||
}
|
||||
/// Get the sole instance of spot::default_environment.
|
||||
static default_environment& instance();
|
||||
protected:
|
||||
default_environment();
|
||||
};
|
||||
}
|
||||
|
|
|
|||
187
src/tl/dot.cc
187
src/tl/dot.cc
|
|
@ -28,110 +28,107 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
namespace
|
||||
{
|
||||
namespace
|
||||
struct dot_printer final
|
||||
{
|
||||
struct dot_printer final
|
||||
{
|
||||
std::ostream& os_;
|
||||
std::unordered_map<formula, int> node_;
|
||||
std::ostringstream* sinks_;
|
||||
std::ostream& os_;
|
||||
std::unordered_map<formula, int> node_;
|
||||
std::ostringstream* sinks_;
|
||||
|
||||
dot_printer(std::ostream& os, formula f)
|
||||
: os_(os), sinks_(new std::ostringstream)
|
||||
{
|
||||
os_ << "digraph G {\n";
|
||||
rec(f);
|
||||
os_ << " subgraph atoms {\n rank=sink;\n"
|
||||
<< sinks_->str() << " }\n}\n";
|
||||
}
|
||||
dot_printer(std::ostream& os, formula f)
|
||||
: os_(os), sinks_(new std::ostringstream)
|
||||
{
|
||||
os_ << "digraph G {\n";
|
||||
rec(f);
|
||||
os_ << " subgraph atoms {\n rank=sink;\n"
|
||||
<< sinks_->str() << " }\n}\n";
|
||||
}
|
||||
|
||||
~dot_printer()
|
||||
~dot_printer()
|
||||
{
|
||||
delete sinks_;
|
||||
}
|
||||
|
||||
int rec(formula f)
|
||||
{
|
||||
auto i = node_.emplace(f, node_.size());
|
||||
int src = i.first->second;
|
||||
if (!i.second)
|
||||
return src;
|
||||
|
||||
op o = f.kind();
|
||||
std::string str = (o == op::ap) ? f.ap_name() : f.kindstr();
|
||||
|
||||
if (o == op::ap || f.is_constant())
|
||||
*sinks_ << " " << src << " [label=\""
|
||||
<< str << "\", shape=box];\n";
|
||||
else
|
||||
os_ << " " << src << " [label=\"" << str << "\"];\n";
|
||||
|
||||
int childnum = 0;
|
||||
switch (o)
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
childnum = 0; // No number for children
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
childnum = -2; // L and R markers
|
||||
break;
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
childnum = 1; // Numbered children
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
os_ << " " << src << " -> " << rec(c);
|
||||
if (childnum > 0)
|
||||
os_ << " [taillabel=\"" << childnum << "\"]";
|
||||
if (childnum == -2)
|
||||
os_ << " [taillabel=\"L\"]";
|
||||
else if (childnum == -1)
|
||||
os_ << " [taillabel=\"R\"]";
|
||||
os_ << ";\n";
|
||||
++childnum;
|
||||
}
|
||||
|
||||
int rec(formula f)
|
||||
{
|
||||
auto i = node_.emplace(f, node_.size());
|
||||
int src = i.first->second;
|
||||
if (!i.second)
|
||||
return src;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
print_dot_psl(std::ostream& os, formula f)
|
||||
{
|
||||
dot_printer p(os, f);
|
||||
return os;
|
||||
}
|
||||
op o = f.kind();
|
||||
std::string str = (o == op::ap) ? f.ap_name() : f.kindstr();
|
||||
|
||||
if (o == op::ap || f.is_constant())
|
||||
*sinks_ << " " << src << " [label=\""
|
||||
<< str << "\", shape=box];\n";
|
||||
else
|
||||
os_ << " " << src << " [label=\"" << str << "\"];\n";
|
||||
|
||||
int childnum = 0;
|
||||
switch (o)
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
childnum = 0; // No number for children
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
childnum = -2; // L and R markers
|
||||
break;
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
childnum = 1; // Numbered children
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
os_ << " " << src << " -> " << rec(c);
|
||||
if (childnum > 0)
|
||||
os_ << " [taillabel=\"" << childnum << "\"]";
|
||||
if (childnum == -2)
|
||||
os_ << " [taillabel=\"L\"]";
|
||||
else if (childnum == -1)
|
||||
os_ << " [taillabel=\"R\"]";
|
||||
os_ << ";\n";
|
||||
++childnum;
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
std::ostream&
|
||||
print_dot_psl(std::ostream& os, formula f)
|
||||
{
|
||||
dot_printer p(os, f);
|
||||
return os;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,16 +26,13 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Write a formula tree using dot's syntax.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
///
|
||||
/// \c dot is part of the GraphViz package
|
||||
/// http://www.graphviz.org/
|
||||
SPOT_API
|
||||
std::ostream& print_dot_psl(std::ostream& os, formula f);
|
||||
}
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Write a formula tree using dot's syntax.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
///
|
||||
/// \c dot is part of the GraphViz package
|
||||
/// http://www.graphviz.org/
|
||||
SPOT_API
|
||||
std::ostream& print_dot_psl(std::ostream& os, formula f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,34 +27,30 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
/// \ingroup ltl_essential
|
||||
/// \brief An environment that describes atomic propositions.
|
||||
class environment
|
||||
{
|
||||
/// \ingroup ltl_essential
|
||||
/// \brief An environment that describes atomic propositions.
|
||||
class environment
|
||||
public:
|
||||
/// \brief Obtain the formula associated to \a prop_str
|
||||
///
|
||||
/// Usually \a prop_str, is the name of an atomic proposition,
|
||||
/// and spot::require simply returns the associated
|
||||
/// spot::formula.
|
||||
///
|
||||
/// Note this is not a \c const method. Some environments will
|
||||
/// "create" the atomic proposition when requested.
|
||||
///
|
||||
/// \return 0 iff \a prop_str is not part of the environment,
|
||||
/// or the associated spot::formula otherwise.
|
||||
virtual formula require(const std::string& prop_str) = 0;
|
||||
|
||||
/// Get the name of the environment.
|
||||
virtual const std::string& name() const = 0;
|
||||
|
||||
virtual
|
||||
~environment()
|
||||
{
|
||||
public:
|
||||
/// \brief Obtain the formula associated to \a prop_str
|
||||
///
|
||||
/// Usually \a prop_str, is the name of an atomic proposition,
|
||||
/// and spot::ltl::require simply returns the associated
|
||||
/// spot::ltl::formula.
|
||||
///
|
||||
/// Note this is not a \c const method. Some environments will
|
||||
/// "create" the atomic proposition when requested.
|
||||
///
|
||||
/// \return 0 iff \a prop_str is not part of the environment,
|
||||
/// or the associated spot::ltl::formula otherwise.
|
||||
virtual formula require(const std::string& prop_str) = 0;
|
||||
|
||||
/// Get the name of the environment.
|
||||
virtual const std::string& name() const = 0;
|
||||
|
||||
virtual
|
||||
~environment()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ namespace spot
|
|||
{
|
||||
namespace
|
||||
{
|
||||
static const std::vector<ltl::formula>
|
||||
static const std::vector<formula>
|
||||
split_aps(const char* arg)
|
||||
{
|
||||
std::vector<ltl::formula> group;
|
||||
std::vector<formula> group;
|
||||
auto start = arg;
|
||||
while (*start)
|
||||
{
|
||||
|
|
@ -61,7 +61,7 @@ namespace spot
|
|||
throw std::invalid_argument(s);
|
||||
}
|
||||
std::string ap(start, end - start);
|
||||
group.emplace_back(ltl::formula::ap(ap));
|
||||
group.emplace_back(formula::ap(ap));
|
||||
do
|
||||
++end;
|
||||
while (*end == ' ' || *end == '\t');
|
||||
|
|
@ -86,7 +86,7 @@ namespace spot
|
|||
while (rend > start && (rend[-1] == ' ' || rend[-1] == '\t'))
|
||||
--rend;
|
||||
std::string ap(start, rend - start);
|
||||
group.emplace_back(ltl::formula::ap(ap));
|
||||
group.emplace_back(formula::ap(ap));
|
||||
if (*end == ',')
|
||||
start = end + 1;
|
||||
else
|
||||
|
|
@ -102,27 +102,27 @@ namespace spot
|
|||
add_group(split_aps(ap_csv));
|
||||
}
|
||||
|
||||
void exclusive_ap::add_group(std::vector<ltl::formula> ap)
|
||||
void exclusive_ap::add_group(std::vector<formula> ap)
|
||||
{
|
||||
groups.push_back(ap);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
ltl::formula
|
||||
nand(ltl::formula lhs, ltl::formula rhs)
|
||||
formula
|
||||
nand(formula lhs, formula rhs)
|
||||
{
|
||||
return ltl::formula::Not(ltl::formula::And({lhs, rhs}));
|
||||
return formula::Not(formula::And({lhs, rhs}));
|
||||
}
|
||||
}
|
||||
|
||||
ltl::formula
|
||||
exclusive_ap::constrain(ltl::formula f) const
|
||||
formula
|
||||
exclusive_ap::constrain(formula f) const
|
||||
{
|
||||
auto* s = atomic_prop_collect(f);
|
||||
|
||||
std::vector<ltl::formula> group;
|
||||
std::vector<ltl::formula> v;
|
||||
std::vector<formula> group;
|
||||
std::vector<formula> v;
|
||||
|
||||
for (auto& g: groups)
|
||||
{
|
||||
|
|
@ -139,7 +139,7 @@ namespace spot
|
|||
};
|
||||
|
||||
delete s;
|
||||
return ltl::formula::And({f, ltl::formula::G(ltl::formula::And(v))});
|
||||
return formula::And({f, formula::G(formula::And(v))});
|
||||
}
|
||||
|
||||
twa_graph_ptr exclusive_ap::constrain(const_twa_graph_ptr aut,
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ namespace spot
|
|||
{
|
||||
class SPOT_API exclusive_ap final
|
||||
{
|
||||
std::vector<std::vector<ltl::formula>> groups;
|
||||
std::vector<std::vector<formula>> groups;
|
||||
public:
|
||||
#ifndef SWIG
|
||||
void add_group(std::vector<ltl::formula> ap);
|
||||
void add_group(std::vector<formula> ap);
|
||||
#endif
|
||||
void add_group(const char* ap_csv);
|
||||
|
||||
|
|
@ -39,7 +39,7 @@ namespace spot
|
|||
return groups.empty();
|
||||
}
|
||||
|
||||
ltl::formula constrain(ltl::formula f) const;
|
||||
formula constrain(formula f) const;
|
||||
twa_graph_ptr constrain(const_twa_graph_ptr aut,
|
||||
bool simplify_guards = false) const;
|
||||
};
|
||||
|
|
|
|||
3116
src/tl/formula.cc
3116
src/tl/formula.cc
File diff suppressed because it is too large
Load diff
2079
src/tl/formula.hh
2079
src/tl/formula.hh
File diff suppressed because it is too large
Load diff
|
|
@ -25,56 +25,53 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
int
|
||||
length(formula f)
|
||||
{
|
||||
int
|
||||
length(formula f)
|
||||
{
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
auto s = x.size();
|
||||
if (s > 1)
|
||||
len += s - 1;
|
||||
else
|
||||
++len;
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
length_boolone(formula f)
|
||||
{
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
if (x.is_boolean())
|
||||
{
|
||||
++len;
|
||||
return true;
|
||||
}
|
||||
auto s = x.size();
|
||||
if (s > 2)
|
||||
{
|
||||
int b = 0;
|
||||
for (const auto& y: x)
|
||||
if (y.is_boolean())
|
||||
++b;
|
||||
len += s - b * 2 + 1;
|
||||
}
|
||||
else if (s > 1)
|
||||
{
|
||||
len += s - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
auto s = x.size();
|
||||
if (s > 1)
|
||||
len += s - 1;
|
||||
else
|
||||
++len;
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
length_boolone(formula f)
|
||||
{
|
||||
int len = 0;
|
||||
f.traverse([&len](const formula& x)
|
||||
{
|
||||
if (x.is_boolean())
|
||||
{
|
||||
++len;
|
||||
return true;
|
||||
}
|
||||
auto s = x.size();
|
||||
if (s > 2)
|
||||
{
|
||||
int b = 0;
|
||||
for (const auto& y: x)
|
||||
if (y.is_boolean())
|
||||
++b;
|
||||
len += s - b * 2 + 1;
|
||||
}
|
||||
else if (s > 1)
|
||||
{
|
||||
len += s - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
++len;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return len;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,28 +26,25 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \ingroup ltl_misc
|
||||
/// \brief Compute the length of a formula.
|
||||
///
|
||||
/// The length of a formula is the number of atomic propositions,
|
||||
/// constants, and operators (logical and temporal) occurring in
|
||||
/// the formula. n-ary operators count for n-1; for instance
|
||||
/// <code>a | b | c</code> has length 5, even if there is only as
|
||||
/// single <code>|</code> node internally.
|
||||
///
|
||||
/// If squash_boolean is set, all Boolean formulae are assumed
|
||||
/// to have length one.
|
||||
SPOT_API
|
||||
int length(formula f);
|
||||
/// \ingroup ltl_misc
|
||||
/// \brief Compute the length of a formula.
|
||||
///
|
||||
/// The length of a formula is the number of atomic propositions,
|
||||
/// constants, and operators (logical and temporal) occurring in
|
||||
/// the formula. n-ary operators count for n-1; for instance
|
||||
/// <code>a | b | c</code> has length 5, even if there is only as
|
||||
/// single <code>|</code> node internally.
|
||||
///
|
||||
/// If squash_boolean is set, all Boolean formulae are assumed
|
||||
/// to have length one.
|
||||
SPOT_API
|
||||
int length(formula f);
|
||||
|
||||
/// \ingroup ltl_misc
|
||||
/// \brief Compute the length of a formula, squashing Boolean formulae
|
||||
///
|
||||
/// This is similar to spot::ltl::length(), except all Boolean
|
||||
/// formulae are assumed to have length one.
|
||||
SPOT_API
|
||||
int length_boolone(formula f);
|
||||
}
|
||||
/// \ingroup ltl_misc
|
||||
/// \brief Compute the length of a formula, squashing Boolean formulae
|
||||
///
|
||||
/// This is similar to spot::length(), except all Boolean
|
||||
/// formulae are assumed to have length one.
|
||||
SPOT_API
|
||||
int length_boolone(formula f);
|
||||
}
|
||||
|
|
|
|||
316
src/tl/mark.cc
316
src/tl/mark.cc
|
|
@ -25,170 +25,166 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
formula
|
||||
mark_tools::mark_concat_ops(formula f)
|
||||
{
|
||||
formula
|
||||
mark_tools::mark_concat_ops(formula f)
|
||||
{
|
||||
f2f_map::iterator i = markops_.find(f);
|
||||
if (i != markops_.end())
|
||||
return i->second;
|
||||
f2f_map::iterator i = markops_.find(f);
|
||||
if (i != markops_.end())
|
||||
return i->second;
|
||||
|
||||
ltl::formula res;
|
||||
switch (f.kind())
|
||||
formula res;
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosureMarked:
|
||||
case op::OrRat:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
res = f;
|
||||
break;
|
||||
case op::NegClosure:
|
||||
res = formula::NegClosureMarked(f[0]);
|
||||
break;
|
||||
case op::EConcat:
|
||||
res = formula::EConcatMarked(f[0], f[1]);
|
||||
break;
|
||||
case op::Or:
|
||||
case op::And:
|
||||
res = f.map([this](formula f)
|
||||
{
|
||||
return this->mark_concat_ops(f);
|
||||
});
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
markops_[f] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
formula
|
||||
mark_tools::simplify_mark(formula f)
|
||||
{
|
||||
if (!f.is_marked())
|
||||
return f;
|
||||
|
||||
f2f_map::iterator i = simpmark_.find(f);
|
||||
if (i != simpmark_.end())
|
||||
return i->second;
|
||||
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->simplify_mark(f);
|
||||
};
|
||||
|
||||
formula res;
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
res = f;
|
||||
break;
|
||||
case op::Or:
|
||||
res = f.map(recurse);
|
||||
break;
|
||||
case op::And:
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosureMarked:
|
||||
case op::OrRat:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
res = f;
|
||||
break;
|
||||
case op::NegClosure:
|
||||
res = ltl::formula::NegClosureMarked(f[0]);
|
||||
break;
|
||||
case op::EConcat:
|
||||
res = ltl::formula::EConcatMarked(f[0], f[1]);
|
||||
break;
|
||||
case op::Or:
|
||||
case op::And:
|
||||
res = f.map([this](formula f)
|
||||
{
|
||||
return this->mark_concat_ops(f);
|
||||
});
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
std::set<std::pair<formula, formula>> empairs;
|
||||
std::set<formula> nmset;
|
||||
std::vector<formula> elist;
|
||||
std::vector<formula> nlist;
|
||||
std::vector<formula> v;
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
if (c.is(op::EConcatMarked))
|
||||
{
|
||||
empairs.emplace(c[0], c[1]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::EConcat))
|
||||
{
|
||||
elist.push_back(c);
|
||||
}
|
||||
else if (c.is(op::NegClosureMarked))
|
||||
{
|
||||
nmset.insert(c[0]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::NegClosure))
|
||||
{
|
||||
nlist.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.push_back(c);
|
||||
}
|
||||
}
|
||||
// Keep only the non-marked EConcat for which we
|
||||
// have not seen a similar EConcatMarked.
|
||||
for (auto e: elist)
|
||||
if (empairs.find(std::make_pair(e[0], e[1]))
|
||||
== empairs.end())
|
||||
v.push_back(e);
|
||||
// Keep only the non-marked NegClosure for which we
|
||||
// have not seen a similar NegClosureMarked.
|
||||
for (auto n: nlist)
|
||||
if (nmset.find(n[0]) == nmset.end())
|
||||
v.push_back(n);
|
||||
res = formula::And(v);
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::OrRat:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
markops_[f] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
formula
|
||||
mark_tools::simplify_mark(formula f)
|
||||
{
|
||||
if (!f.is_marked())
|
||||
return f;
|
||||
|
||||
f2f_map::iterator i = simpmark_.find(f);
|
||||
if (i != simpmark_.end())
|
||||
return i->second;
|
||||
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->simplify_mark(f);
|
||||
};
|
||||
|
||||
ltl::formula res;
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
res = f;
|
||||
break;
|
||||
case op::Or:
|
||||
res = f.map(recurse);
|
||||
break;
|
||||
case op::And:
|
||||
{
|
||||
std::set<std::pair<formula, formula>> empairs;
|
||||
std::set<formula> nmset;
|
||||
std::vector<formula> elist;
|
||||
std::vector<formula> nlist;
|
||||
std::vector<formula> v;
|
||||
|
||||
for (auto c: f)
|
||||
{
|
||||
if (c.is(op::EConcatMarked))
|
||||
{
|
||||
empairs.emplace(c[0], c[1]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::EConcat))
|
||||
{
|
||||
elist.push_back(c);
|
||||
}
|
||||
else if (c.is(op::NegClosureMarked))
|
||||
{
|
||||
nmset.insert(c[0]);
|
||||
v.push_back(c.map(recurse));
|
||||
}
|
||||
else if (c.is(op::NegClosure))
|
||||
{
|
||||
nlist.push_back(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
v.push_back(c);
|
||||
}
|
||||
}
|
||||
// Keep only the non-marked EConcat for which we
|
||||
// have not seen a similar EConcatMarked.
|
||||
for (auto e: elist)
|
||||
if (empairs.find(std::make_pair(e[0], e[1]))
|
||||
== empairs.end())
|
||||
v.push_back(e);
|
||||
// Keep only the non-marked NegClosure for which we
|
||||
// have not seen a similar NegClosureMarked.
|
||||
for (auto n: nlist)
|
||||
if (nmset.find(n[0]) == nmset.end())
|
||||
v.push_back(n);
|
||||
res = ltl::formula::And(v);
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::OrRat:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
SPOT_UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
simpmark_[f] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
simpmark_[f] = res;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,24 +24,20 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
class mark_tools final
|
||||
{
|
||||
class mark_tools final
|
||||
{
|
||||
public:
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Mark operators NegClosure and EConcat.
|
||||
///
|
||||
/// \param f The formula to rewrite.
|
||||
formula mark_concat_ops(formula f);
|
||||
public:
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Mark operators NegClosure and EConcat.
|
||||
///
|
||||
/// \param f The formula to rewrite.
|
||||
formula mark_concat_ops(formula f);
|
||||
|
||||
formula simplify_mark(formula f);
|
||||
formula simplify_mark(formula f);
|
||||
|
||||
private:
|
||||
typedef std::unordered_map<formula, formula> f2f_map;
|
||||
f2f_map simpmark_;
|
||||
f2f_map markops_;
|
||||
};
|
||||
|
||||
}
|
||||
private:
|
||||
typedef std::unordered_map<formula, formula> f2f_map;
|
||||
f2f_map simpmark_;
|
||||
f2f_map markops_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,340 +32,337 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
namespace
|
||||
{
|
||||
namespace
|
||||
formula substitute_ap(formula f, formula ap_src, formula ap_dst)
|
||||
{
|
||||
formula substitute_ap(formula f, formula ap_src, formula ap_dst)
|
||||
return f.map([&](formula f)
|
||||
{
|
||||
if (f == ap_src)
|
||||
return ap_dst;
|
||||
else
|
||||
return substitute_ap(f, ap_src, ap_dst);
|
||||
});
|
||||
}
|
||||
|
||||
typedef std::vector<formula> vec;
|
||||
class mutator final
|
||||
{
|
||||
int mutation_counter_ = 0;
|
||||
formula f_;
|
||||
unsigned opts_;
|
||||
public:
|
||||
mutator(formula f, unsigned opts) : f_(f), opts_(opts)
|
||||
{
|
||||
return f.map([&](formula f)
|
||||
{
|
||||
if (f == ap_src)
|
||||
return ap_dst;
|
||||
else
|
||||
return substitute_ap(f, ap_src, ap_dst);
|
||||
});
|
||||
}
|
||||
|
||||
typedef std::vector<formula> vec;
|
||||
class mutator final
|
||||
formula mutate(formula f)
|
||||
{
|
||||
int mutation_counter_ = 0;
|
||||
formula f_;
|
||||
unsigned opts_;
|
||||
public:
|
||||
mutator(formula f, unsigned opts) : f_(f), opts_(opts)
|
||||
{
|
||||
}
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->mutate(f);
|
||||
};
|
||||
|
||||
formula mutate(formula f)
|
||||
{
|
||||
auto recurse = [this](formula f)
|
||||
{
|
||||
return this->mutate(f);
|
||||
};
|
||||
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
return f;
|
||||
case op::ap:
|
||||
if (opts_ & Mut_Ap2Const)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::tt();
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::ff();
|
||||
}
|
||||
return f;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
if ((opts_ & Mut_Remove_Ops)
|
||||
&& mutation_counter_-- == 0)
|
||||
return f[0];
|
||||
// fall through
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
case op::ap:
|
||||
if (opts_ & Mut_Ap2Const)
|
||||
else
|
||||
return f.map(recurse);
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
{
|
||||
int mos = f.size();
|
||||
if (opts_ & Mut_Remove_Multop_Operands)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::tt();
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::ff();
|
||||
for (int i = 0; i < mos; ++i)
|
||||
if (mutation_counter_-- == 0)
|
||||
return f.all_but(i);
|
||||
}
|
||||
return f;
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
if ((opts_ & Mut_Remove_Ops)
|
||||
&& mutation_counter_-- == 0)
|
||||
return f[0];
|
||||
// fall through
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
|
||||
if (opts_ & Mut_Split_Ops && f.is(op::AndNLM))
|
||||
{
|
||||
if (mutation_counter_ >= 0
|
||||
&& mutation_counter_ < 2 * (mos - 1))
|
||||
{
|
||||
vec v1;
|
||||
vec v2;
|
||||
v1.push_back(f[0]);
|
||||
bool reverse = false;
|
||||
int i = 1;
|
||||
while (i < mos)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
break;
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
reverse = true;
|
||||
break;
|
||||
}
|
||||
v1.push_back(f[i++]);
|
||||
}
|
||||
for (; i < mos; ++i)
|
||||
v2.push_back(f[i]);
|
||||
formula first = AndNLM_(v1);
|
||||
formula second = AndNLM_(v2);
|
||||
formula ost = formula::one_star();
|
||||
if (!reverse)
|
||||
return AndRat_(Concat_(first, ost), second);
|
||||
else
|
||||
return AndRat_(Concat_(second, ost), first);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutation_counter_ -= 2 * (mos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
{
|
||||
int mos = f.size();
|
||||
if (opts_ & Mut_Remove_Multop_Operands)
|
||||
{
|
||||
for (int i = 0; i < mos; ++i)
|
||||
if (mutation_counter_-- == 0)
|
||||
return f.all_but(i);
|
||||
}
|
||||
|
||||
if (opts_ & Mut_Split_Ops && f.is(op::AndNLM))
|
||||
{
|
||||
if (mutation_counter_ >= 0
|
||||
&& mutation_counter_ < 2 * (mos - 1))
|
||||
{
|
||||
vec v1;
|
||||
vec v2;
|
||||
v1.push_back(f[0]);
|
||||
bool reverse = false;
|
||||
int i = 1;
|
||||
while (i < mos)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
break;
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
reverse = true;
|
||||
break;
|
||||
}
|
||||
v1.push_back(f[i++]);
|
||||
}
|
||||
for (; i < mos; ++i)
|
||||
v2.push_back(f[i]);
|
||||
formula first = AndNLM_(v1);
|
||||
formula second = AndNLM_(v2);
|
||||
formula ost = formula::one_star();
|
||||
if (!reverse)
|
||||
return AndRat_(Concat_(first, ost), second);
|
||||
else
|
||||
return AndRat_(Concat_(second, ost), first);
|
||||
}
|
||||
else
|
||||
{
|
||||
mutation_counter_ -= 2 * (mos - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
{
|
||||
formula first = f[0];
|
||||
formula second = f[1];
|
||||
op o = f.kind();
|
||||
bool left_is_sere = o == op::EConcat
|
||||
|| o == op::EConcatMarked
|
||||
|| o == op::UConcat;
|
||||
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
{
|
||||
if (!left_is_sere)
|
||||
return first;
|
||||
else if (o == op::UConcat)
|
||||
return formula::NegClosure(first);
|
||||
else // EConcat or EConcatMarked
|
||||
return formula::Closure(first);
|
||||
}
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return second;
|
||||
if (opts_ & Mut_Rewrite_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::U:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(first, second);
|
||||
break;
|
||||
case op::M:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::R(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::U(second, first);
|
||||
break;
|
||||
case op::R:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(second, first);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::Equiv:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(second, first);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, second});
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
// Negate the two argument sequentially (in this
|
||||
// case right before left, otherwise different
|
||||
// compilers will make different choices.
|
||||
auto right = formula::Not(second);
|
||||
return formula::And({formula::Not(first), right});
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, formula::Not(second)});
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({formula::Not(first), second});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
{
|
||||
formula c = f[0];
|
||||
op o = f.kind();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return c;
|
||||
if (opts_ & Mut_Simplify_Bounds)
|
||||
{
|
||||
auto min = f.min();
|
||||
auto max = f.max();
|
||||
if (min > 0)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min - 1, max);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, 0, max);
|
||||
}
|
||||
if (max != formula::unbounded())
|
||||
{
|
||||
if (max > min && mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min, max - 1);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min,
|
||||
formula::unbounded());
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
{
|
||||
formula first = f[0];
|
||||
formula second = f[1];
|
||||
op o = f.kind();
|
||||
bool left_is_sere = o == op::EConcat
|
||||
|| o == op::EConcatMarked
|
||||
|| o == op::UConcat;
|
||||
|
||||
formula
|
||||
get_mutation(int n)
|
||||
{
|
||||
mutation_counter_ = n;
|
||||
formula mut = mutate(f_);
|
||||
if (mut == f_)
|
||||
return nullptr;
|
||||
return mut;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool
|
||||
formula_length_less_than(formula left, formula right)
|
||||
{
|
||||
assert(left != nullptr);
|
||||
assert(right != nullptr);
|
||||
if (left == right)
|
||||
return false;
|
||||
auto ll = length(left);
|
||||
auto lr = length(right);
|
||||
if (ll < lr)
|
||||
return true;
|
||||
if (ll > lr)
|
||||
return false;
|
||||
return left < right;
|
||||
}
|
||||
|
||||
typedef std::set<formula> fset_t;
|
||||
|
||||
void
|
||||
single_mutation_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula mut;
|
||||
int i = 0;
|
||||
mutator mv(f, opts);
|
||||
while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr))
|
||||
single_mutation_rec(mut, mutations, opts, n, m - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
replace_ap_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
auto aps =
|
||||
std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f));
|
||||
for (auto ap1: *aps)
|
||||
for (auto ap2: *aps)
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
{
|
||||
if (ap1 == ap2)
|
||||
continue;
|
||||
auto mut = substitute_ap(f, ap1, ap2);
|
||||
replace_ap_rec(mut, mutations, opts, n, m - 1);
|
||||
if (!n)
|
||||
return;
|
||||
if (!left_is_sere)
|
||||
return first;
|
||||
else if (o == op::UConcat)
|
||||
return formula::NegClosure(first);
|
||||
else // EConcat or EConcatMarked
|
||||
return formula::Closure(first);
|
||||
}
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return second;
|
||||
if (opts_ & Mut_Rewrite_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::U:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(first, second);
|
||||
break;
|
||||
case op::M:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::R(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::U(second, first);
|
||||
break;
|
||||
case op::R:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::W(second, first);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opts_ & Mut_Split_Ops)
|
||||
{
|
||||
switch (o)
|
||||
{
|
||||
case op::Equiv:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(first, second);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::Implies(second, first);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, second});
|
||||
if (mutation_counter_-- == 0)
|
||||
{
|
||||
// Negate the two argument sequentially (in this
|
||||
// case right before left, otherwise different
|
||||
// compilers will make different choices.
|
||||
auto right = formula::Not(second);
|
||||
return formula::And({formula::Not(first), right});
|
||||
}
|
||||
break;
|
||||
case op::Xor:
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({first, formula::Not(second)});
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::And({formula::Not(first), second});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
{
|
||||
formula c = f[0];
|
||||
op o = f.kind();
|
||||
if (opts_ & Mut_Remove_Ops && mutation_counter_-- == 0)
|
||||
return c;
|
||||
if (opts_ & Mut_Simplify_Bounds)
|
||||
{
|
||||
auto min = f.min();
|
||||
auto max = f.max();
|
||||
if (min > 0)
|
||||
{
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min - 1, max);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, 0, max);
|
||||
}
|
||||
if (max != formula::unbounded())
|
||||
{
|
||||
if (max > min && mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min, max - 1);
|
||||
if (mutation_counter_-- == 0)
|
||||
return formula::bunop(o, c, min,
|
||||
formula::unbounded());
|
||||
}
|
||||
}
|
||||
if (mutation_counter_ < 0)
|
||||
return f;
|
||||
else
|
||||
return f.map(recurse);
|
||||
}
|
||||
}
|
||||
SPOT_UNREACHABLE();
|
||||
}
|
||||
|
||||
formula
|
||||
get_mutation(int n)
|
||||
{
|
||||
mutation_counter_ = n;
|
||||
formula mut = mutate(f_);
|
||||
if (mut == f_)
|
||||
return nullptr;
|
||||
return mut;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
bool
|
||||
formula_length_less_than(formula left, formula right)
|
||||
{
|
||||
assert(left != nullptr);
|
||||
assert(right != nullptr);
|
||||
if (left == right)
|
||||
return false;
|
||||
auto ll = length(left);
|
||||
auto lr = length(right);
|
||||
if (ll < lr)
|
||||
return true;
|
||||
if (ll > lr)
|
||||
return false;
|
||||
return left < right;
|
||||
}
|
||||
|
||||
std::vector<formula>
|
||||
mutate(formula f, unsigned opts, unsigned max_output,
|
||||
unsigned mutation_count, bool sort)
|
||||
{
|
||||
fset_t mutations;
|
||||
single_mutation_rec(f, mutations, opts, max_output, mutation_count);
|
||||
if (opts & Mut_Remove_One_Ap)
|
||||
replace_ap_rec(f, mutations, opts, max_output, mutation_count);
|
||||
typedef std::set<formula> fset_t;
|
||||
|
||||
vec res(mutations.begin(), mutations.end());
|
||||
if (sort)
|
||||
std::sort(res.begin(), res.end(), formula_length_less_than);
|
||||
return res;
|
||||
void
|
||||
single_mutation_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula mut;
|
||||
int i = 0;
|
||||
mutator mv(f, opts);
|
||||
while (n > 0 && ((mut = mv.get_mutation(i++)) != nullptr))
|
||||
single_mutation_rec(mut, mutations, opts, n, m - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
replace_ap_rec(formula f, fset_t& mutations, unsigned opts,
|
||||
unsigned& n, unsigned m)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
if (mutations.insert(f).second)
|
||||
--n;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!n)
|
||||
return;
|
||||
auto aps =
|
||||
std::unique_ptr<atomic_prop_set>(atomic_prop_collect(f));
|
||||
for (auto ap1: *aps)
|
||||
for (auto ap2: *aps)
|
||||
{
|
||||
if (ap1 == ap2)
|
||||
continue;
|
||||
auto mut = substitute_ap(f, ap1, ap2);
|
||||
replace_ap_rec(mut, mutations, opts, n, m - 1);
|
||||
if (!n)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<formula>
|
||||
mutate(formula f, unsigned opts, unsigned max_output,
|
||||
unsigned mutation_count, bool sort)
|
||||
{
|
||||
fset_t mutations;
|
||||
single_mutation_rec(f, mutations, opts, max_output, mutation_count);
|
||||
if (opts & Mut_Remove_One_Ap)
|
||||
replace_ap_rec(f, mutations, opts, max_output, mutation_count);
|
||||
|
||||
vec res(mutations.begin(), mutations.end());
|
||||
if (sort)
|
||||
std::sort(res.begin(), res.end(), formula_length_less_than);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,25 +24,22 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
enum mut_opts
|
||||
{
|
||||
Mut_Ap2Const = 1U<<0,
|
||||
Mut_Simplify_Bounds = 1U<<1,
|
||||
Mut_Remove_Multop_Operands = 1U<<2,
|
||||
Mut_Remove_Ops = 1U<<3,
|
||||
Mut_Split_Ops = 1U<<4,
|
||||
Mut_Rewrite_Ops = 1U<<5,
|
||||
Mut_Remove_One_Ap = 1U<<6,
|
||||
Mut_All = -1U
|
||||
};
|
||||
enum mut_opts
|
||||
{
|
||||
Mut_Ap2Const = 1U<<0,
|
||||
Mut_Simplify_Bounds = 1U<<1,
|
||||
Mut_Remove_Multop_Operands = 1U<<2,
|
||||
Mut_Remove_Ops = 1U<<3,
|
||||
Mut_Split_Ops = 1U<<4,
|
||||
Mut_Rewrite_Ops = 1U<<5,
|
||||
Mut_Remove_One_Ap = 1U<<6,
|
||||
Mut_All = -1U
|
||||
};
|
||||
|
||||
SPOT_API
|
||||
std::vector<formula> mutate(formula f,
|
||||
unsigned opts = Mut_All,
|
||||
unsigned max_output = -1U,
|
||||
unsigned mutation_count = 1,
|
||||
bool sort = true);
|
||||
}
|
||||
SPOT_API
|
||||
std::vector<formula> mutate(formula f,
|
||||
unsigned opts = Mut_All,
|
||||
unsigned max_output = -1U,
|
||||
unsigned mutation_count = 1,
|
||||
bool sort = true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,17 +25,13 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
formula
|
||||
negative_normal_form(formula f, bool negated)
|
||||
{
|
||||
formula
|
||||
negative_normal_form(formula f, bool negated)
|
||||
{
|
||||
if (!negated && f.is_in_nenoform())
|
||||
return f;
|
||||
|
||||
ltl_simplifier s;
|
||||
return s.negative_normal_form(f, negated);
|
||||
}
|
||||
if (!negated && f.is_in_nenoform())
|
||||
return f;
|
||||
|
||||
ltl_simplifier s;
|
||||
return s.negative_normal_form(f, negated);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,24 +26,21 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Build the negative normal form of \a f.
|
||||
///
|
||||
/// All negations of the formula are pushed in front of the
|
||||
/// atomic propositions.
|
||||
///
|
||||
/// \param f The formula to normalize.
|
||||
/// \param negated If \c true, return the negative normal form of
|
||||
/// \c !f
|
||||
///
|
||||
/// Note that this will not remove abbreviated operators. If you
|
||||
/// want to remove abbreviations, call spot::ltl::unabbreviate
|
||||
/// first. (Calling this function after
|
||||
/// spot::ltl::negative_normal_form would likely produce a formula
|
||||
/// which is not in negative normal form.)
|
||||
SPOT_API formula
|
||||
negative_normal_form(formula f, bool negated = false);
|
||||
}
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Build the negative normal form of \a f.
|
||||
///
|
||||
/// All negations of the formula are pushed in front of the
|
||||
/// atomic propositions.
|
||||
///
|
||||
/// \param f The formula to normalize.
|
||||
/// \param negated If \c true, return the negative normal form of
|
||||
/// \c !f
|
||||
///
|
||||
/// Note that this will not remove abbreviated operators. If you
|
||||
/// want to remove abbreviations, call spot::unabbreviate
|
||||
/// first. (Calling this function after
|
||||
/// spot::negative_normal_form would likely produce a formula
|
||||
/// which is not in negative normal form.)
|
||||
SPOT_API formula
|
||||
negative_normal_form(formula f, bool negated = false);
|
||||
}
|
||||
|
|
|
|||
2152
src/tl/print.cc
2152
src/tl/print.cc
File diff suppressed because it is too large
Load diff
359
src/tl/print.hh
359
src/tl/print.hh
|
|
@ -27,198 +27,195 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \addtogroup ltl_io
|
||||
/// @{
|
||||
/// \addtogroup ltl_io
|
||||
/// @{
|
||||
|
||||
/// \brief Output a PSL formula as a string which is parsable.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_psl(std::ostream& os, formula f, bool full_parent = false);
|
||||
/// \brief Output a PSL formula as a string which is parsable.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_psl(std::ostream& os, formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Convert a PSL formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_psl(formula f, bool full_parent = false);
|
||||
/// \brief Convert a PSL formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_psl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a PSL formula as an utf-8 string which is parsable.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_psl(std::ostream& os, formula f,
|
||||
/// \brief Output a PSL formula as an utf-8 string which is parsable.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a PSL formula into a utf-8 string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_psl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a string which is parsable.
|
||||
/// \param f The formula to translate.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sere(std::ostream& os, formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sere(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a utf-8 string which is parsable.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_sere(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output an LTL formula as a string parsable by Spin.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_spin_ltl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert an LTL formula into a string parsable by Spin.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_spin_ltl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output an LTL formula as a string parsable by Wring.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
SPOT_API std::ostream&
|
||||
print_wring_ltl(std::ostream& os, formula f);
|
||||
|
||||
/// \brief Convert a formula into a string parsable by Wring
|
||||
/// \param f The formula to translate.
|
||||
SPOT_API std::string
|
||||
str_wring_ltl(formula f);
|
||||
|
||||
/// \brief Output a PSL formula as a LaTeX string.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_psl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a LaTeX string.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a PSL formula into a utf-8 string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_psl(formula f, bool full_parent = false);
|
||||
/// \brief Output a SERE formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_sere(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a string which is parsable.
|
||||
/// \param f The formula to translate.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sere(std::ostream& os, formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sere(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a utf-8 string which is parsable.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_utf8_sere(std::ostream& os, formula f,
|
||||
/// \brief Output a PSL formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed back.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert a SERE formula into a string which is parsable
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_utf8_sere(formula f, bool full_parent = false);
|
||||
/// \brief Output a PSL formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_psl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output an LTL formula as a string parsable by Spin.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_spin_ltl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Convert an LTL formula into a string parsable by Spin.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_spin_ltl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output an LTL formula as a string parsable by Wring.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
SPOT_API std::ostream&
|
||||
print_wring_ltl(std::ostream& os, formula f);
|
||||
|
||||
/// \brief Convert a formula into a string parsable by Wring
|
||||
/// \param f The formula to translate.
|
||||
SPOT_API std::string
|
||||
str_wring_ltl(formula f);
|
||||
|
||||
/// \brief Output a PSL formula as a LaTeX string.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_psl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a LaTeX string.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_latex_sere(std::ostream& os, formula f,
|
||||
/// \brief Output a SERE formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed back.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a LaTeX string which is parsable.
|
||||
/// unless the formula contains automaton operators (used in ELTL formulae).
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_latex_sere(formula f, bool full_parent = false);
|
||||
/// \brief Output a SERE formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_sere(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a PSL formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed back.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_psl(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
/// \brief Output an LTL formula as a string in LBT's format.
|
||||
///
|
||||
/// The formula must be an LTL formula (ELTL and PSL operators
|
||||
/// are not supported). The M and W operator will be output
|
||||
/// as-is, because this is accepted by LBTT, however if you
|
||||
/// plan to use the output with other tools, you should probably
|
||||
/// rewrite these two operators using unabbreviate_wm().
|
||||
///
|
||||
/// \param f The formula to translate.
|
||||
/// \param os The stream where it should be output.
|
||||
SPOT_API std::ostream&
|
||||
print_lbt_ltl(std::ostream& os, formula f);
|
||||
|
||||
/// \brief Output a PSL formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_psl(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed back.
|
||||
/// \param os The stream where it should be output.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::ostream&
|
||||
print_sclatex_sere(std::ostream& os, formula f,
|
||||
bool full_parent = false);
|
||||
|
||||
/// \brief Output a SERE formula as a self-contained LaTeX string.
|
||||
///
|
||||
/// The result cannot be parsed bacl.
|
||||
/// \param f The formula to translate.
|
||||
/// \param full_parent Whether or not the string should by fully
|
||||
/// parenthesized.
|
||||
SPOT_API std::string
|
||||
str_sclatex_sere(formula f, bool full_parent = false);
|
||||
|
||||
/// \brief Output an LTL formula as a string in LBT's format.
|
||||
///
|
||||
/// The formula must be an LTL formula (ELTL and PSL operators
|
||||
/// are not supported). The M and W operator will be output
|
||||
/// as-is, because this is accepted by LBTT, however if you
|
||||
/// plan to use the output with other tools, you should probably
|
||||
/// rewrite these two operators using unabbreviate_wm().
|
||||
///
|
||||
/// \param f The formula to translate.
|
||||
/// \param os The stream where it should be output.
|
||||
SPOT_API std::ostream&
|
||||
print_lbt_ltl(std::ostream& os, formula f);
|
||||
|
||||
/// \brief Output an LTL formula as a string in LBT's format.
|
||||
///
|
||||
/// The formula must be an LTL formula (ELTL and PSL operators
|
||||
/// are not supported). The M and W operator will be output
|
||||
/// as-is, because this is accepted by LBTT, however if you
|
||||
/// plan to use the output with other tools, you should probably
|
||||
/// rewrite these two operators using unabbreviate_wm().
|
||||
///
|
||||
/// \param f The formula to translate.
|
||||
SPOT_API std::string
|
||||
str_lbt_ltl(formula f);
|
||||
/// @}
|
||||
}
|
||||
/// \brief Output an LTL formula as a string in LBT's format.
|
||||
///
|
||||
/// The formula must be an LTL formula (ELTL and PSL operators
|
||||
/// are not supported). The M and W operator will be output
|
||||
/// as-is, because this is accepted by LBTT, however if you
|
||||
/// plan to use the output with other tools, you should probably
|
||||
/// rewrite these two operators using unabbreviate_wm().
|
||||
///
|
||||
/// \param f The formula to translate.
|
||||
SPOT_API std::string
|
||||
str_lbt_ltl(formula f);
|
||||
/// @}
|
||||
}
|
||||
|
|
|
|||
1009
src/tl/randomltl.cc
1009
src/tl/randomltl.cc
File diff suppressed because it is too large
Load diff
|
|
@ -38,316 +38,312 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Base class for random formula generators
|
||||
class SPOT_API random_formula
|
||||
{
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Base class for random formula generators
|
||||
class SPOT_API random_formula
|
||||
public:
|
||||
random_formula(unsigned proba_size,
|
||||
const atomic_prop_set* ap):
|
||||
proba_size_(proba_size), proba_(new op_proba[proba_size_]), ap_(ap)
|
||||
{
|
||||
public:
|
||||
random_formula(unsigned proba_size,
|
||||
const atomic_prop_set* ap):
|
||||
proba_size_(proba_size), proba_(new op_proba[proba_size_]), ap_(ap)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~random_formula()
|
||||
{
|
||||
delete[] proba_;
|
||||
}
|
||||
virtual ~random_formula()
|
||||
{
|
||||
delete[] proba_;
|
||||
}
|
||||
|
||||
/// Return the set of atomic proposition used to build formulae.
|
||||
const atomic_prop_set*
|
||||
/// Return the set of atomic proposition used to build formulae.
|
||||
const atomic_prop_set*
|
||||
ap() const
|
||||
{
|
||||
return ap_;
|
||||
}
|
||||
|
||||
/// \brief Generate a formula of size \a n.
|
||||
///
|
||||
/// It is possible to obtain formulae that are smaller than \a
|
||||
/// n, because some simple simplifications are performed by the
|
||||
/// AST. (For instance the formula <code>a | a</code> is
|
||||
/// automatically reduced to <code>a</code> by spot::ltl::multop.)
|
||||
formula generate(int n) const;
|
||||
|
||||
/// \brief Print the priorities of each operator, constants,
|
||||
/// and atomic propositions.
|
||||
std::ostream& dump_priorities(std::ostream& os) const;
|
||||
|
||||
/// \brief Update the priorities used to generate the formulae.
|
||||
///
|
||||
/// \a options should be comma-separated list of KEY=VALUE
|
||||
/// assignments, using keys from the above list.
|
||||
/// For instance <code>"xor=0, F=3"</code> will prevent \c xor
|
||||
/// from being used, and will raise the relative probability of
|
||||
/// occurrences of the \c F operator.
|
||||
const char* parse_options(char* options);
|
||||
|
||||
protected:
|
||||
void update_sums();
|
||||
|
||||
struct op_proba
|
||||
{
|
||||
const char* name;
|
||||
int min_n;
|
||||
double proba;
|
||||
typedef formula (*builder)(const random_formula* rl, int n);
|
||||
builder build;
|
||||
void setup(const char* name, int min_n, builder build);
|
||||
};
|
||||
unsigned proba_size_;
|
||||
op_proba* proba_;
|
||||
double total_1_;
|
||||
op_proba* proba_2_;
|
||||
double total_2_;
|
||||
op_proba* proba_2_or_more_;
|
||||
double total_2_and_more_;
|
||||
const atomic_prop_set* ap_;
|
||||
};
|
||||
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random LTL formulae.
|
||||
///
|
||||
/// This class recursively constructs LTL formulae of a given
|
||||
/// size. The formulae will use the use atomic propositions from
|
||||
/// the set of propositions passed to the constructor, in addition
|
||||
/// to the constant and all LTL operators supported by Spot.
|
||||
///
|
||||
/// By default each operator has equal chance to be selected.
|
||||
/// Also, each atomic proposition has as much chance as each
|
||||
/// constant (i.e., true and false) to be picked. This can be
|
||||
/// tuned using parse_options().
|
||||
class SPOT_API random_ltl: public random_formula
|
||||
{
|
||||
public:
|
||||
/// Create a random LTL generator using atomic propositions from \a ap.
|
||||
///
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
///
|
||||
/// This means that each operator has equal chance to be
|
||||
/// selected. Also, each atomic proposition has as much chance
|
||||
/// as each constant (i.e., true and false) to be picked.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
random_ltl(const atomic_prop_set* ap);
|
||||
return ap_;
|
||||
}
|
||||
|
||||
protected:
|
||||
void setup_proba_();
|
||||
random_ltl(int size, const atomic_prop_set* ap);
|
||||
};
|
||||
/// \brief Generate a formula of size \a n.
|
||||
///
|
||||
/// It is possible to obtain formulae that are smaller than \a
|
||||
/// n, because some simple simplifications are performed by the
|
||||
/// AST. (For instance the formula <code>a | a</code> is
|
||||
/// automatically reduced to <code>a</code> by spot::multop.)
|
||||
formula generate(int n) const;
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random Boolean formulae.
|
||||
/// \brief Print the priorities of each operator, constants,
|
||||
/// and atomic propositions.
|
||||
std::ostream& dump_priorities(std::ostream& os) const;
|
||||
|
||||
/// \brief Update the priorities used to generate the formulae.
|
||||
///
|
||||
/// This class recursively constructs Boolean formulae of a given size.
|
||||
/// The formulae will use the use atomic propositions from the
|
||||
/// set of propositions passed to the constructor, in addition to the
|
||||
/// constant and all Boolean operators supported by Spot.
|
||||
///
|
||||
/// By default each operator has equal chance to be selected.
|
||||
class SPOT_API random_boolean: public random_formula
|
||||
/// \a options should be comma-separated list of KEY=VALUE
|
||||
/// assignments, using keys from the above list.
|
||||
/// For instance <code>"xor=0, F=3"</code> will prevent \c xor
|
||||
/// from being used, and will raise the relative probability of
|
||||
/// occurrences of the \c F operator.
|
||||
const char* parse_options(char* options);
|
||||
|
||||
protected:
|
||||
void update_sums();
|
||||
|
||||
struct op_proba
|
||||
{
|
||||
public:
|
||||
/// Create a random Boolean formula generator using atomic
|
||||
/// propositions from \a ap.
|
||||
///
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
///
|
||||
/// This means that each operator has equal chance to be
|
||||
/// selected. Also, each atomic proposition has as much chance
|
||||
/// as each constant (i.e., true and false) to be picked.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
random_boolean(const atomic_prop_set* ap);
|
||||
const char* name;
|
||||
int min_n;
|
||||
double proba;
|
||||
typedef formula (*builder)(const random_formula* rl, int n);
|
||||
builder build;
|
||||
void setup(const char* name, int min_n, builder build);
|
||||
};
|
||||
unsigned proba_size_;
|
||||
op_proba* proba_;
|
||||
double total_1_;
|
||||
op_proba* proba_2_;
|
||||
double total_2_;
|
||||
op_proba* proba_2_or_more_;
|
||||
double total_2_and_more_;
|
||||
const atomic_prop_set* ap_;
|
||||
};
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random SERE.
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random LTL formulae.
|
||||
///
|
||||
/// This class recursively constructs LTL formulae of a given
|
||||
/// size. The formulae will use the use atomic propositions from
|
||||
/// the set of propositions passed to the constructor, in addition
|
||||
/// to the constant and all LTL operators supported by Spot.
|
||||
///
|
||||
/// By default each operator has equal chance to be selected.
|
||||
/// Also, each atomic proposition has as much chance as each
|
||||
/// constant (i.e., true and false) to be picked. This can be
|
||||
/// tuned using parse_options().
|
||||
class SPOT_API random_ltl: public random_formula
|
||||
{
|
||||
public:
|
||||
/// Create a random LTL generator using atomic propositions from \a ap.
|
||||
///
|
||||
/// This class recursively constructs SERE of a given size.
|
||||
/// The formulae will use the use atomic propositions from the
|
||||
/// set of propositions passed to the constructor, in addition to the
|
||||
/// constant and all SERE operators supported by Spot.
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/// By default each operator has equal chance to be selected.
|
||||
class SPOT_API random_sere: public random_formula
|
||||
{
|
||||
public:
|
||||
/// Create a random SERE genere using atomic propositions from \a ap.
|
||||
///
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
eword 1
|
||||
boolform 1
|
||||
star 1
|
||||
star_b 1
|
||||
equal_b 1
|
||||
goto_b 1
|
||||
and 1
|
||||
andNLM 1
|
||||
or 1
|
||||
concat 1
|
||||
fusion 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where "boolfrom" designates a Boolean formula generated
|
||||
/// by random_boolean.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
///
|
||||
/// In addition, you can set the properties of the Boolean
|
||||
/// formula generator used to build Boolean subformulae using
|
||||
/// the parse_options method of the \c rb attribute.
|
||||
random_sere(const atomic_prop_set* ap);
|
||||
|
||||
random_boolean rb;
|
||||
};
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random PSL formulae.
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// This class recursively constructs PSL formulae of a given size.
|
||||
/// The formulae will use the use atomic propositions from the
|
||||
/// set of propositions passed to the constructor, in addition to the
|
||||
/// constant and all PSL operators supported by Spot.
|
||||
class SPOT_API random_psl: public random_ltl
|
||||
{
|
||||
public:
|
||||
/// Create a random PSL generator using atomic propositions from \a ap.
|
||||
///
|
||||
/// PSL formulae are built by combining LTL operators, plus
|
||||
/// three operators (EConcat, UConcat, Closure) taking a SERE
|
||||
/// as parameter.
|
||||
///
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
Closure 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
EConcat 1
|
||||
UConcat 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
///
|
||||
/// This means that each operator has equal chance to be
|
||||
/// selected. Also, each atomic proposition has as much chance
|
||||
/// as each constant (i.e., true and false) to be picked.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
///
|
||||
/// In addition, you can set the properties of the SERE generator
|
||||
/// used to build SERE subformulae using the parse_options method
|
||||
/// of the \c rs attribute.
|
||||
random_psl(const atomic_prop_set* ap);
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
///
|
||||
/// This means that each operator has equal chance to be
|
||||
/// selected. Also, each atomic proposition has as much chance
|
||||
/// as each constant (i.e., true and false) to be picked.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
random_ltl(const atomic_prop_set* ap);
|
||||
|
||||
/// The SERE generator used to generate SERE subformulae.
|
||||
random_sere rs;
|
||||
};
|
||||
protected:
|
||||
void setup_proba_();
|
||||
random_ltl(int size, const atomic_prop_set* ap);
|
||||
};
|
||||
|
||||
class SPOT_API randltlgenerator
|
||||
{
|
||||
typedef std::unordered_set<formula> fset_t;
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random Boolean formulae.
|
||||
///
|
||||
/// This class recursively constructs Boolean formulae of a given size.
|
||||
/// The formulae will use the use atomic propositions from the
|
||||
/// set of propositions passed to the constructor, in addition to the
|
||||
/// constant and all Boolean operators supported by Spot.
|
||||
///
|
||||
/// By default each operator has equal chance to be selected.
|
||||
class SPOT_API random_boolean: public random_formula
|
||||
{
|
||||
public:
|
||||
/// Create a random Boolean formula generator using atomic
|
||||
/// propositions from \a ap.
|
||||
///
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
and 1
|
||||
or 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
///
|
||||
/// This means that each operator has equal chance to be
|
||||
/// selected. Also, each atomic proposition has as much chance
|
||||
/// as each constant (i.e., true and false) to be picked.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
random_boolean(const atomic_prop_set* ap);
|
||||
};
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random SERE.
|
||||
///
|
||||
/// This class recursively constructs SERE of a given size.
|
||||
/// The formulae will use the use atomic propositions from the
|
||||
/// set of propositions passed to the constructor, in addition to the
|
||||
/// constant and all SERE operators supported by Spot.
|
||||
///
|
||||
/// By default each operator has equal chance to be selected.
|
||||
class SPOT_API random_sere: public random_formula
|
||||
{
|
||||
public:
|
||||
/// Create a random SERE genere using atomic propositions from \a ap.
|
||||
///
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
eword 1
|
||||
boolform 1
|
||||
star 1
|
||||
star_b 1
|
||||
equal_b 1
|
||||
goto_b 1
|
||||
and 1
|
||||
andNLM 1
|
||||
or 1
|
||||
concat 1
|
||||
fusion 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where "boolfrom" designates a Boolean formula generated
|
||||
/// by random_boolean.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
///
|
||||
/// In addition, you can set the properties of the Boolean
|
||||
/// formula generator used to build Boolean subformulae using
|
||||
/// the parse_options method of the \c rb attribute.
|
||||
random_sere(const atomic_prop_set* ap);
|
||||
|
||||
random_boolean rb;
|
||||
};
|
||||
|
||||
/// \ingroup ltl_io
|
||||
/// \brief Generate random PSL formulae.
|
||||
///
|
||||
/// This class recursively constructs PSL formulae of a given size.
|
||||
/// The formulae will use the use atomic propositions from the
|
||||
/// set of propositions passed to the constructor, in addition to the
|
||||
/// constant and all PSL operators supported by Spot.
|
||||
class SPOT_API random_psl: public random_ltl
|
||||
{
|
||||
public:
|
||||
/// Create a random PSL generator using atomic propositions from \a ap.
|
||||
///
|
||||
/// PSL formulae are built by combining LTL operators, plus
|
||||
/// three operators (EConcat, UConcat, Closure) taking a SERE
|
||||
/// as parameter.
|
||||
///
|
||||
/// The default priorities are defined as follows:
|
||||
///
|
||||
/** \verbatim
|
||||
ap n
|
||||
false 1
|
||||
true 1
|
||||
not 1
|
||||
F 1
|
||||
G 1
|
||||
X 1
|
||||
Closure 1
|
||||
equiv 1
|
||||
implies 1
|
||||
xor 1
|
||||
R 1
|
||||
U 1
|
||||
W 1
|
||||
M 1
|
||||
and 1
|
||||
or 1
|
||||
EConcat 1
|
||||
UConcat 1
|
||||
\endverbatim */
|
||||
///
|
||||
/// Where \c n is the number of atomic propositions in the
|
||||
/// set passed to the constructor.
|
||||
///
|
||||
/// This means that each operator has equal chance to be
|
||||
/// selected. Also, each atomic proposition has as much chance
|
||||
/// as each constant (i.e., true and false) to be picked.
|
||||
///
|
||||
/// These priorities can be changed use the parse_options method.
|
||||
///
|
||||
/// In addition, you can set the properties of the SERE generator
|
||||
/// used to build SERE subformulae using the parse_options method
|
||||
/// of the \c rs attribute.
|
||||
random_psl(const atomic_prop_set* ap);
|
||||
|
||||
/// The SERE generator used to generate SERE subformulae.
|
||||
random_sere rs;
|
||||
};
|
||||
|
||||
class SPOT_API randltlgenerator
|
||||
{
|
||||
typedef std::unordered_set<formula> fset_t;
|
||||
|
||||
|
||||
public:
|
||||
randltlgenerator(int aprops_n, const option_map& opts,
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
public:
|
||||
randltlgenerator(int aprops_n, const option_map& opts,
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
|
||||
randltlgenerator(atomic_prop_set aprops, const option_map& opts,
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
randltlgenerator(atomic_prop_set aprops, const option_map& opts,
|
||||
char* opt_pL = nullptr,
|
||||
char* opt_pS = nullptr,
|
||||
char* opt_pB = nullptr);
|
||||
|
||||
~randltlgenerator();
|
||||
~randltlgenerator();
|
||||
|
||||
formula next();
|
||||
formula next();
|
||||
|
||||
void dump_ltl_priorities(std::ostream& os);
|
||||
void dump_bool_priorities(std::ostream& os);
|
||||
void dump_psl_priorities(std::ostream& os);
|
||||
void dump_sere_priorities(std::ostream& os);
|
||||
void dump_sere_bool_priorities(std::ostream& os);
|
||||
void remove_some_props(atomic_prop_set& s);
|
||||
void dump_ltl_priorities(std::ostream& os);
|
||||
void dump_bool_priorities(std::ostream& os);
|
||||
void dump_psl_priorities(std::ostream& os);
|
||||
void dump_sere_priorities(std::ostream& os);
|
||||
void dump_sere_bool_priorities(std::ostream& os);
|
||||
void remove_some_props(atomic_prop_set& s);
|
||||
|
||||
formula GF_n();
|
||||
formula GF_n();
|
||||
|
||||
private:
|
||||
fset_t unique_set_;
|
||||
atomic_prop_set aprops_;
|
||||
private:
|
||||
fset_t unique_set_;
|
||||
atomic_prop_set aprops_;
|
||||
|
||||
int opt_seed_;
|
||||
int opt_tree_size_min_;
|
||||
int opt_tree_size_max_;
|
||||
bool opt_unique_;
|
||||
bool opt_wf_;
|
||||
int opt_simpl_level_;
|
||||
ltl_simplifier simpl_;
|
||||
int opt_seed_;
|
||||
int opt_tree_size_min_;
|
||||
int opt_tree_size_max_;
|
||||
bool opt_unique_;
|
||||
bool opt_wf_;
|
||||
int opt_simpl_level_;
|
||||
ltl_simplifier simpl_;
|
||||
|
||||
int output_;
|
||||
int output_;
|
||||
|
||||
random_formula* rf_ = nullptr;
|
||||
random_psl* rp_ = nullptr;
|
||||
random_sere* rs_ = nullptr;
|
||||
};
|
||||
}
|
||||
random_formula* rf_ = nullptr;
|
||||
random_psl* rp_ = nullptr;
|
||||
random_sere* rs_ = nullptr;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,461 +27,457 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Basic relabeler
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Basic relabeler
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
struct ap_generator
|
||||
{
|
||||
struct ap_generator
|
||||
{
|
||||
virtual formula next() = 0;
|
||||
virtual ~ap_generator() {}
|
||||
};
|
||||
virtual formula next() = 0;
|
||||
virtual ~ap_generator() {}
|
||||
};
|
||||
|
||||
struct pnn_generator final: ap_generator
|
||||
{
|
||||
unsigned nn;
|
||||
pnn_generator()
|
||||
: nn(0)
|
||||
{
|
||||
}
|
||||
|
||||
formula next()
|
||||
{
|
||||
std::ostringstream s;
|
||||
s << 'p' << nn++;
|
||||
return formula::ap(s.str());
|
||||
}
|
||||
};
|
||||
|
||||
struct abc_generator final: ap_generator
|
||||
{
|
||||
public:
|
||||
abc_generator()
|
||||
: nn(0)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned nn;
|
||||
|
||||
formula next()
|
||||
{
|
||||
std::string s;
|
||||
unsigned n = nn++;
|
||||
do
|
||||
{
|
||||
s.push_back('a' + (n % 26));
|
||||
n /= 26;
|
||||
}
|
||||
while (n);
|
||||
return formula::ap(s);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class relabeler
|
||||
{
|
||||
public:
|
||||
typedef std::unordered_map<formula, formula> map;
|
||||
map newname;
|
||||
ap_generator* gen;
|
||||
relabeling_map* oldnames;
|
||||
|
||||
relabeler(ap_generator* gen, relabeling_map* m)
|
||||
: gen(gen), oldnames(m)
|
||||
{
|
||||
}
|
||||
|
||||
~relabeler()
|
||||
{
|
||||
delete gen;
|
||||
}
|
||||
|
||||
formula rename(formula old)
|
||||
{
|
||||
auto r = newname.emplace(old, nullptr);
|
||||
if (!r.second)
|
||||
{
|
||||
return r.first->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula res = gen->next();
|
||||
r.first->second = res;
|
||||
if (oldnames)
|
||||
(*oldnames)[res] = old;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
formula
|
||||
visit(formula f)
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
return rename(f);
|
||||
else
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return this->visit(f);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
formula
|
||||
relabel(formula f, relabeling_style style, relabeling_map* m)
|
||||
struct pnn_generator final: ap_generator
|
||||
{
|
||||
ap_generator* gen = nullptr;
|
||||
switch (style)
|
||||
unsigned nn;
|
||||
pnn_generator()
|
||||
: nn(0)
|
||||
{
|
||||
case Pnn:
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
case Abc:
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
}
|
||||
|
||||
relabeler r(gen, m);
|
||||
return r.visit(f);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Boolean-subexpression relabeler
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Here we want to rewrite a formula such as
|
||||
// "a & b & X(c & d) & GF(c & d)" into "p0 & Xp1 & GFp1"
|
||||
// where Boolean subexpressions are replaced by fresh propositions.
|
||||
//
|
||||
// Detecting Boolean subexpressions is not a problem.
|
||||
// Furthermore, because we are already representing LTL formulas
|
||||
// with sharing of identical sub-expressions we can easily rename
|
||||
// a subexpression (such as c&d above) only once. However this
|
||||
// scheme has two problems:
|
||||
//
|
||||
// 1. It will not detect inter-dependent Boolean subexpressions.
|
||||
// For instance it will mistakenly relabel "(a & b) U (a & !b)"
|
||||
// as "p0 U p1", hiding the dependency between a&b and a&!b.
|
||||
//
|
||||
// 2. Because of our n-ary operators, it will fail to
|
||||
// notice that (a & b) is a sub-expression of (a & b & c).
|
||||
//
|
||||
// The code below only addresses point 1 so that interdependent
|
||||
// subexpressions are not relabeled. Point 2 could be improved in
|
||||
// a future version of somebody feels inclined to do so.
|
||||
//
|
||||
// The way we compute the subexpressions that can be relabeled is
|
||||
// by transforming the formula syntax tree into an undirected
|
||||
// graph, and computing the cut points of this graph. The cut
|
||||
// points (or articulation points) are the nodes whose removal
|
||||
// would split the graph in two components. To ensure that a
|
||||
// Boolean operator is only considered as a cut point if it would
|
||||
// separate all of its children from the rest of the graph, we
|
||||
// connect all the children of Boolean operators.
|
||||
//
|
||||
// For instance (a & b) U (c & d) has two (Boolean) cut points
|
||||
// corresponding to the two AND operators:
|
||||
//
|
||||
// (a&b)U(c&d)
|
||||
// ╱ ╲
|
||||
// a&b c&d
|
||||
// ╱ ╲ ╱ ╲
|
||||
// a─────b c─────d
|
||||
//
|
||||
// (The root node is also a cut-point, but we only consider Boolean
|
||||
// cut-points for relabeling.)
|
||||
//
|
||||
// On the other hand, (a & b) U (b & !c) has only one Boolean
|
||||
// cut-point which corresponds to the NOT operator:
|
||||
//
|
||||
// (a&b)U(b&!c)
|
||||
// ╱ ╲
|
||||
// a&b b&c
|
||||
// ╱ ╲ ╱ ╲
|
||||
// a─────b────!c
|
||||
// │
|
||||
// c
|
||||
//
|
||||
// Note that if the children of a&b and b&c were not connected,
|
||||
// a&b and b&c would be considered as cut points because they
|
||||
// separate "a" or "!c" from the rest of the graph.
|
||||
//
|
||||
// The relabeling of a formula is therefore done in 3 passes:
|
||||
// 1. convert the formula's syntax tree into an undirected graph,
|
||||
// adding links between children of Boolean operators
|
||||
// 2. compute the (Boolean) cut points of that graph, using the
|
||||
// Hopcroft-Tarjan algorithm (see below for a reference)
|
||||
// 3. recursively scan the formula's tree until we reach
|
||||
// either a (Boolean) cut point or an atomic proposition, and
|
||||
// replace that node by a fresh atomic proposition.
|
||||
//
|
||||
// In the example above (a&b)U(b&!c), the last recursion
|
||||
// stop a, b, and !c, producing (p0&p1)U(p1&p2).
|
||||
namespace
|
||||
{
|
||||
typedef std::vector<formula> succ_vec;
|
||||
typedef std::map<formula, succ_vec> fgraph;
|
||||
|
||||
// Convert the formula's syntax tree into an undirected graph
|
||||
// labeled by subformulas.
|
||||
class formula_to_fgraph final
|
||||
formula next()
|
||||
{
|
||||
public:
|
||||
fgraph& g;
|
||||
std::stack<formula> s;
|
||||
std::ostringstream s;
|
||||
s << 'p' << nn++;
|
||||
return formula::ap(s.str());
|
||||
}
|
||||
};
|
||||
|
||||
formula_to_fgraph(fgraph& g):
|
||||
g(g)
|
||||
struct abc_generator final: ap_generator
|
||||
{
|
||||
public:
|
||||
abc_generator()
|
||||
: nn(0)
|
||||
{
|
||||
}
|
||||
|
||||
~formula_to_fgraph()
|
||||
{
|
||||
}
|
||||
unsigned nn;
|
||||
|
||||
void
|
||||
visit(formula f)
|
||||
{
|
||||
formula next()
|
||||
{
|
||||
std::string s;
|
||||
unsigned n = nn++;
|
||||
do
|
||||
{
|
||||
// Connect to parent
|
||||
auto in = g.emplace(f, succ_vec());
|
||||
if (!s.empty())
|
||||
{
|
||||
formula top = s.top();
|
||||
in.first->second.push_back(top);
|
||||
g[top].push_back(f);
|
||||
if (!in.second)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(in.second);
|
||||
}
|
||||
s.push_back('a' + (n % 26));
|
||||
n /= 26;
|
||||
}
|
||||
s.push(f);
|
||||
while (n);
|
||||
return formula::ap(s);
|
||||
}
|
||||
};
|
||||
|
||||
unsigned sz = f.size();
|
||||
unsigned i = 0;
|
||||
if (sz > 2 && !f.is_boolean())
|
||||
|
||||
class relabeler
|
||||
{
|
||||
public:
|
||||
typedef std::unordered_map<formula, formula> map;
|
||||
map newname;
|
||||
ap_generator* gen;
|
||||
relabeling_map* oldnames;
|
||||
|
||||
relabeler(ap_generator* gen, relabeling_map* m)
|
||||
: gen(gen), oldnames(m)
|
||||
{
|
||||
}
|
||||
|
||||
~relabeler()
|
||||
{
|
||||
delete gen;
|
||||
}
|
||||
|
||||
formula rename(formula old)
|
||||
{
|
||||
auto r = newname.emplace(old, nullptr);
|
||||
if (!r.second)
|
||||
{
|
||||
return r.first->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula res = gen->next();
|
||||
r.first->second = res;
|
||||
if (oldnames)
|
||||
(*oldnames)[res] = old;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
formula
|
||||
visit(formula f)
|
||||
{
|
||||
if (f.is(op::ap))
|
||||
return rename(f);
|
||||
else
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return this->visit(f);
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
formula
|
||||
relabel(formula f, relabeling_style style, relabeling_map* m)
|
||||
{
|
||||
ap_generator* gen = nullptr;
|
||||
switch (style)
|
||||
{
|
||||
case Pnn:
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
case Abc:
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
}
|
||||
|
||||
relabeler r(gen, m);
|
||||
return r.visit(f);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Boolean-subexpression relabeler
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Here we want to rewrite a formula such as
|
||||
// "a & b & X(c & d) & GF(c & d)" into "p0 & Xp1 & GFp1"
|
||||
// where Boolean subexpressions are replaced by fresh propositions.
|
||||
//
|
||||
// Detecting Boolean subexpressions is not a problem.
|
||||
// Furthermore, because we are already representing LTL formulas
|
||||
// with sharing of identical sub-expressions we can easily rename
|
||||
// a subexpression (such as c&d above) only once. However this
|
||||
// scheme has two problems:
|
||||
//
|
||||
// 1. It will not detect inter-dependent Boolean subexpressions.
|
||||
// For instance it will mistakenly relabel "(a & b) U (a & !b)"
|
||||
// as "p0 U p1", hiding the dependency between a&b and a&!b.
|
||||
//
|
||||
// 2. Because of our n-ary operators, it will fail to
|
||||
// notice that (a & b) is a sub-expression of (a & b & c).
|
||||
//
|
||||
// The code below only addresses point 1 so that interdependent
|
||||
// subexpressions are not relabeled. Point 2 could be improved in
|
||||
// a future version of somebody feels inclined to do so.
|
||||
//
|
||||
// The way we compute the subexpressions that can be relabeled is
|
||||
// by transforming the formula syntax tree into an undirected
|
||||
// graph, and computing the cut points of this graph. The cut
|
||||
// points (or articulation points) are the nodes whose removal
|
||||
// would split the graph in two components. To ensure that a
|
||||
// Boolean operator is only considered as a cut point if it would
|
||||
// separate all of its children from the rest of the graph, we
|
||||
// connect all the children of Boolean operators.
|
||||
//
|
||||
// For instance (a & b) U (c & d) has two (Boolean) cut points
|
||||
// corresponding to the two AND operators:
|
||||
//
|
||||
// (a&b)U(c&d)
|
||||
// ╱ ╲
|
||||
// a&b c&d
|
||||
// ╱ ╲ ╱ ╲
|
||||
// a─────b c─────d
|
||||
//
|
||||
// (The root node is also a cut-point, but we only consider Boolean
|
||||
// cut-points for relabeling.)
|
||||
//
|
||||
// On the other hand, (a & b) U (b & !c) has only one Boolean
|
||||
// cut-point which corresponds to the NOT operator:
|
||||
//
|
||||
// (a&b)U(b&!c)
|
||||
// ╱ ╲
|
||||
// a&b b&c
|
||||
// ╱ ╲ ╱ ╲
|
||||
// a─────b────!c
|
||||
// │
|
||||
// c
|
||||
//
|
||||
// Note that if the children of a&b and b&c were not connected,
|
||||
// a&b and b&c would be considered as cut points because they
|
||||
// separate "a" or "!c" from the rest of the graph.
|
||||
//
|
||||
// The relabeling of a formula is therefore done in 3 passes:
|
||||
// 1. convert the formula's syntax tree into an undirected graph,
|
||||
// adding links between children of Boolean operators
|
||||
// 2. compute the (Boolean) cut points of that graph, using the
|
||||
// Hopcroft-Tarjan algorithm (see below for a reference)
|
||||
// 3. recursively scan the formula's tree until we reach
|
||||
// either a (Boolean) cut point or an atomic proposition, and
|
||||
// replace that node by a fresh atomic proposition.
|
||||
//
|
||||
// In the example above (a&b)U(b&!c), the last recursion
|
||||
// stop a, b, and !c, producing (p0&p1)U(p1&p2).
|
||||
namespace
|
||||
{
|
||||
typedef std::vector<formula> succ_vec;
|
||||
typedef std::map<formula, succ_vec> fgraph;
|
||||
|
||||
// Convert the formula's syntax tree into an undirected graph
|
||||
// labeled by subformulas.
|
||||
class formula_to_fgraph final
|
||||
{
|
||||
public:
|
||||
fgraph& g;
|
||||
std::stack<formula> s;
|
||||
|
||||
formula_to_fgraph(fgraph& g):
|
||||
g(g)
|
||||
{
|
||||
}
|
||||
|
||||
~formula_to_fgraph()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
visit(formula f)
|
||||
{
|
||||
{
|
||||
// Connect to parent
|
||||
auto in = g.emplace(f, succ_vec());
|
||||
if (!s.empty())
|
||||
{
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
visit(b);
|
||||
formula top = s.top();
|
||||
in.first->second.push_back(top);
|
||||
g[top].push_back(f);
|
||||
if (!in.second)
|
||||
return;
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
visit(f[i]);
|
||||
if (sz > 1 && f.is_boolean())
|
||||
else
|
||||
{
|
||||
// For Boolean nodes, connect all children in a
|
||||
// loop. This way the node can only be a cut-point
|
||||
// if it separates all children from the reset of
|
||||
// the graph (not only one).
|
||||
formula pred = f[0];
|
||||
for (i = 1; i < sz; ++i)
|
||||
assert(in.second);
|
||||
}
|
||||
}
|
||||
s.push(f);
|
||||
|
||||
unsigned sz = f.size();
|
||||
unsigned i = 0;
|
||||
if (sz > 2 && !f.is_boolean())
|
||||
{
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
visit(b);
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
visit(f[i]);
|
||||
if (sz > 1 && f.is_boolean())
|
||||
{
|
||||
// For Boolean nodes, connect all children in a
|
||||
// loop. This way the node can only be a cut-point
|
||||
// if it separates all children from the reset of
|
||||
// the graph (not only one).
|
||||
formula pred = f[0];
|
||||
for (i = 1; i < sz; ++i)
|
||||
{
|
||||
formula next = f[i];
|
||||
// Note that we only add an edge in one
|
||||
// direction, because we are building a cycle
|
||||
// between all children anyway.
|
||||
g[pred].push_back(next);
|
||||
pred = next;
|
||||
}
|
||||
g[pred].push_back(f[0]);
|
||||
}
|
||||
s.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::set<formula> fset;
|
||||
struct data_entry // for each node of the graph
|
||||
{
|
||||
unsigned num; // serial number, in pre-order
|
||||
unsigned low; // lowest number accessible via unstacked descendants
|
||||
data_entry(unsigned num = 0, unsigned low = 0)
|
||||
: num(num), low(low)
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef std::unordered_map<formula, data_entry> fmap_t;
|
||||
struct stack_entry
|
||||
{
|
||||
formula grand_parent;
|
||||
formula parent; // current node
|
||||
succ_vec::const_iterator current_child;
|
||||
succ_vec::const_iterator last_child;
|
||||
};
|
||||
typedef std::stack<stack_entry> stack_t;
|
||||
|
||||
// Fill c with the Boolean cutpoints of g, starting from start.
|
||||
//
|
||||
// This is based no "Efficient Algorithms for Graph
|
||||
// Manipulation", J. Hopcroft & R. Tarjan, in Communications of
|
||||
// the ACM, 16 (6), June 1973.
|
||||
//
|
||||
// It differs from the original algorithm by returning only the
|
||||
// Boolean cutpoints, and not dealing with the initial state
|
||||
// properly (our initial state will always be considered as a
|
||||
// cut-point, but since we only return Boolean cut-points it's
|
||||
// OK: if the top-most formula is Boolean we want to replace it
|
||||
// as a whole).
|
||||
void cut_points(const fgraph& g, fset& c, formula start)
|
||||
{
|
||||
stack_t s;
|
||||
|
||||
unsigned num = 0;
|
||||
fmap_t data;
|
||||
data_entry d = { num, num };
|
||||
data[start] = d;
|
||||
++num;
|
||||
const succ_vec& children = g.find(start)->second;
|
||||
stack_entry e = { start, start, children.begin(), children.end() };
|
||||
s.push(e);
|
||||
|
||||
while (!s.empty())
|
||||
{
|
||||
stack_entry& e = s.top();
|
||||
if (e.current_child != e.last_child)
|
||||
{
|
||||
// Skip the edge if it is just the reverse of the one
|
||||
// we took.
|
||||
formula child = *e.current_child;
|
||||
if (child == e.grand_parent)
|
||||
{
|
||||
formula next = f[i];
|
||||
// Note that we only add an edge in one
|
||||
// direction, because we are building a cycle
|
||||
// between all children anyway.
|
||||
g[pred].push_back(next);
|
||||
pred = next;
|
||||
++e.current_child;
|
||||
continue;
|
||||
}
|
||||
g[pred].push_back(f[0]);
|
||||
}
|
||||
s.pop();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
typedef std::set<formula> fset;
|
||||
struct data_entry // for each node of the graph
|
||||
{
|
||||
unsigned num; // serial number, in pre-order
|
||||
unsigned low; // lowest number accessible via unstacked descendants
|
||||
data_entry(unsigned num = 0, unsigned low = 0)
|
||||
: num(num), low(low)
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef std::unordered_map<formula, data_entry> fmap_t;
|
||||
struct stack_entry
|
||||
{
|
||||
formula grand_parent;
|
||||
formula parent; // current node
|
||||
succ_vec::const_iterator current_child;
|
||||
succ_vec::const_iterator last_child;
|
||||
};
|
||||
typedef std::stack<stack_entry> stack_t;
|
||||
|
||||
// Fill c with the Boolean cutpoints of g, starting from start.
|
||||
//
|
||||
// This is based no "Efficient Algorithms for Graph
|
||||
// Manipulation", J. Hopcroft & R. Tarjan, in Communications of
|
||||
// the ACM, 16 (6), June 1973.
|
||||
//
|
||||
// It differs from the original algorithm by returning only the
|
||||
// Boolean cutpoints, and not dealing with the initial state
|
||||
// properly (our initial state will always be considered as a
|
||||
// cut-point, but since we only return Boolean cut-points it's
|
||||
// OK: if the top-most formula is Boolean we want to replace it
|
||||
// as a whole).
|
||||
void cut_points(const fgraph& g, fset& c, formula start)
|
||||
{
|
||||
stack_t s;
|
||||
|
||||
unsigned num = 0;
|
||||
fmap_t data;
|
||||
data_entry d = { num, num };
|
||||
data[start] = d;
|
||||
++num;
|
||||
const succ_vec& children = g.find(start)->second;
|
||||
stack_entry e = { start, start, children.begin(), children.end() };
|
||||
s.push(e);
|
||||
|
||||
while (!s.empty())
|
||||
{
|
||||
stack_entry& e = s.top();
|
||||
if (e.current_child != e.last_child)
|
||||
{
|
||||
// Skip the edge if it is just the reverse of the one
|
||||
// we took.
|
||||
formula child = *e.current_child;
|
||||
if (child == e.grand_parent)
|
||||
{
|
||||
++e.current_child;
|
||||
continue;
|
||||
}
|
||||
auto i = data.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(child),
|
||||
std::forward_as_tuple(num, num));
|
||||
if (i.second) // New destination.
|
||||
{
|
||||
++num;
|
||||
const succ_vec& children = g.find(child)->second;
|
||||
stack_entry newe = { e.parent, child,
|
||||
children.begin(), children.end() };
|
||||
s.push(newe);
|
||||
}
|
||||
else // Destination exists.
|
||||
{
|
||||
data_entry& dparent = data[e.parent];
|
||||
data_entry& dchild = i.first->second;
|
||||
// If this is a back-edge, update
|
||||
// the low field of the parent.
|
||||
if (dchild.num <= dparent.num)
|
||||
if (dparent.low > dchild.num)
|
||||
dparent.low = dchild.num;
|
||||
}
|
||||
++e.current_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
formula grand_parent = e.grand_parent;
|
||||
formula parent = e.parent;
|
||||
s.pop();
|
||||
if (!s.empty())
|
||||
{
|
||||
data_entry& dparent = data[parent];
|
||||
data_entry& dgrand_parent = data[grand_parent];
|
||||
if (dparent.low >= dgrand_parent.num // cut-point
|
||||
&& grand_parent.is_boolean())
|
||||
c.insert(grand_parent);
|
||||
if (dparent.low < dgrand_parent.low)
|
||||
dgrand_parent.low = dparent.low;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class bse_relabeler final: public relabeler
|
||||
{
|
||||
public:
|
||||
fset& c;
|
||||
bse_relabeler(ap_generator* gen, fset& c,
|
||||
relabeling_map* m)
|
||||
: relabeler(gen, m), c(c)
|
||||
{
|
||||
}
|
||||
|
||||
using relabeler::visit;
|
||||
|
||||
formula
|
||||
visit(formula f)
|
||||
{
|
||||
if (f.is(op::ap) || (c.find(f) != c.end()))
|
||||
return rename(f);
|
||||
|
||||
unsigned sz = f.size();
|
||||
if (sz <= 2)
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return visit(f);
|
||||
});
|
||||
|
||||
unsigned i = 0;
|
||||
std::vector<formula> res;
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
{
|
||||
res.reserve(sz - i + 1);
|
||||
res.push_back(visit(b));
|
||||
auto i = data.emplace(std::piecewise_construct,
|
||||
std::forward_as_tuple(child),
|
||||
std::forward_as_tuple(num, num));
|
||||
if (i.second) // New destination.
|
||||
{
|
||||
++num;
|
||||
const succ_vec& children = g.find(child)->second;
|
||||
stack_entry newe = { e.parent, child,
|
||||
children.begin(), children.end() };
|
||||
s.push(newe);
|
||||
}
|
||||
else // Destination exists.
|
||||
{
|
||||
data_entry& dparent = data[e.parent];
|
||||
data_entry& dchild = i.first->second;
|
||||
// If this is a back-edge, update
|
||||
// the low field of the parent.
|
||||
if (dchild.num <= dparent.num)
|
||||
if (dparent.low > dchild.num)
|
||||
dparent.low = dchild.num;
|
||||
}
|
||||
++e.current_child;
|
||||
}
|
||||
else
|
||||
{
|
||||
res.reserve(sz);
|
||||
formula grand_parent = e.grand_parent;
|
||||
formula parent = e.parent;
|
||||
s.pop();
|
||||
if (!s.empty())
|
||||
{
|
||||
data_entry& dparent = data[parent];
|
||||
data_entry& dgrand_parent = data[grand_parent];
|
||||
if (dparent.low >= dgrand_parent.num // cut-point
|
||||
&& grand_parent.is_boolean())
|
||||
c.insert(grand_parent);
|
||||
if (dparent.low < dgrand_parent.low)
|
||||
dgrand_parent.low = dparent.low;
|
||||
}
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
res.push_back(visit(f[i]));
|
||||
return formula::multop(f.kind(), res);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
formula
|
||||
relabel_bse(formula f, relabeling_style style, relabeling_map* m)
|
||||
class bse_relabeler final: public relabeler
|
||||
{
|
||||
fgraph g;
|
||||
|
||||
// Build the graph g from the formula f.
|
||||
public:
|
||||
fset& c;
|
||||
bse_relabeler(ap_generator* gen, fset& c,
|
||||
relabeling_map* m)
|
||||
: relabeler(gen, m), c(c)
|
||||
{
|
||||
formula_to_fgraph conv(g);
|
||||
conv.visit(f);
|
||||
}
|
||||
|
||||
// Compute its cut-points
|
||||
fset c;
|
||||
cut_points(g, c, f);
|
||||
using relabeler::visit;
|
||||
|
||||
// Relabel the formula recursively, stopping
|
||||
// at cut-points or atomic propositions.
|
||||
ap_generator* gen = nullptr;
|
||||
switch (style)
|
||||
{
|
||||
case Pnn:
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
case Abc:
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
}
|
||||
bse_relabeler rel(gen, c, m);
|
||||
return rel.visit(f);
|
||||
formula
|
||||
visit(formula f)
|
||||
{
|
||||
if (f.is(op::ap) || (c.find(f) != c.end()))
|
||||
return rename(f);
|
||||
|
||||
unsigned sz = f.size();
|
||||
if (sz <= 2)
|
||||
return f.map([this](formula f)
|
||||
{
|
||||
return visit(f);
|
||||
});
|
||||
|
||||
unsigned i = 0;
|
||||
std::vector<formula> res;
|
||||
/// If we have a formula like (a & b & Xc), consider
|
||||
/// it as ((a & b) & Xc) in the graph to isolate the
|
||||
/// Boolean operands as a single node.
|
||||
formula b = f.boolean_operands(&i);
|
||||
if (b)
|
||||
{
|
||||
res.reserve(sz - i + 1);
|
||||
res.push_back(visit(b));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.reserve(sz);
|
||||
}
|
||||
for (; i < sz; ++i)
|
||||
res.push_back(visit(f[i]));
|
||||
return formula::multop(f.kind(), res);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
formula
|
||||
relabel_bse(formula f, relabeling_style style, relabeling_map* m)
|
||||
{
|
||||
fgraph g;
|
||||
|
||||
// Build the graph g from the formula f.
|
||||
{
|
||||
formula_to_fgraph conv(g);
|
||||
conv.visit(f);
|
||||
}
|
||||
|
||||
// Compute its cut-points
|
||||
fset c;
|
||||
cut_points(g, c, f);
|
||||
|
||||
// Relabel the formula recursively, stopping
|
||||
// at cut-points or atomic propositions.
|
||||
ap_generator* gen = nullptr;
|
||||
switch (style)
|
||||
{
|
||||
case Pnn:
|
||||
gen = new pnn_generator;
|
||||
break;
|
||||
case Abc:
|
||||
gen = new abc_generator;
|
||||
break;
|
||||
}
|
||||
bse_relabeler rel(gen, c, m);
|
||||
return rel.visit(f);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,30 +25,27 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
enum relabeling_style { Abc, Pnn };
|
||||
enum relabeling_style { Abc, Pnn };
|
||||
|
||||
typedef std::map<formula, formula> relabeling_map;
|
||||
typedef std::map<formula, formula> relabeling_map;
|
||||
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Relabel the atomic propositions in a formula.
|
||||
///
|
||||
/// If \a m is non-null, it is filled with correspondence
|
||||
/// between the new names (keys) and the old names (values).
|
||||
SPOT_API
|
||||
formula relabel(formula f, relabeling_style style,
|
||||
relabeling_map* m = nullptr);
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Relabel the atomic propositions in a formula.
|
||||
///
|
||||
/// If \a m is non-null, it is filled with correspondence
|
||||
/// between the new names (keys) and the old names (values).
|
||||
SPOT_API
|
||||
formula relabel(formula f, relabeling_style style,
|
||||
relabeling_map* m = nullptr);
|
||||
|
||||
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Relabel Boolean subexpressions in a formula using
|
||||
/// atomic propositions.
|
||||
///
|
||||
/// If \a m is non-null, it is filled with correspondence
|
||||
/// between the new names (keys) and the old names (values).
|
||||
SPOT_API
|
||||
formula relabel_bse(formula f, relabeling_style style,
|
||||
relabeling_map* m = nullptr);
|
||||
}
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Relabel Boolean subexpressions in a formula using
|
||||
/// atomic propositions.
|
||||
///
|
||||
/// If \a m is non-null, it is filled with correspondence
|
||||
/// between the new names (keys) and the old names (values).
|
||||
SPOT_API
|
||||
formula relabel_bse(formula f, relabeling_style style,
|
||||
relabeling_map* m = nullptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,80 +23,77 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
namespace
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static formula
|
||||
remove_x_rec(formula f, atomic_prop_set& aps)
|
||||
{
|
||||
if (f.is_syntactic_stutter_invariant())
|
||||
return f;
|
||||
|
||||
auto rec = [&aps](formula f)
|
||||
{
|
||||
return remove_x_rec(f, aps);
|
||||
};
|
||||
|
||||
if (!f.is(op::X))
|
||||
return f.map(rec);
|
||||
|
||||
formula c = rec(f[0]);
|
||||
|
||||
std::vector<formula> vo;
|
||||
for (auto i: aps)
|
||||
{
|
||||
// First line
|
||||
std::vector<formula> va1;
|
||||
formula npi = formula::Not(i);
|
||||
va1.push_back(i);
|
||||
va1.push_back(formula::U(i, formula::And({npi, c})));
|
||||
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), npi);
|
||||
va1.push_back(formula::Or({formula::U(j, npi), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va1));
|
||||
// Second line
|
||||
std::vector<formula> va2;
|
||||
va2.push_back(npi);
|
||||
va2.push_back(formula::U(npi, formula::And({i, c})));
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), i);
|
||||
va2.push_back(formula::Or({formula::U(j, i), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va2));
|
||||
}
|
||||
// Third line
|
||||
std::vector<formula> va3;
|
||||
for (auto i: aps)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::G(formula::Not(i));
|
||||
va3.push_back(formula::Or({formula::G(i), tmp}));
|
||||
}
|
||||
va3.push_back(c);
|
||||
vo.push_back(formula::And(va3));
|
||||
return formula::Or(vo);
|
||||
}
|
||||
}
|
||||
|
||||
formula remove_x(formula f)
|
||||
static formula
|
||||
remove_x_rec(formula f, atomic_prop_set& aps)
|
||||
{
|
||||
if (f.is_syntactic_stutter_invariant())
|
||||
return f;
|
||||
atomic_prop_set aps;
|
||||
atomic_prop_collect(f, &aps);
|
||||
return remove_x_rec(f, aps);
|
||||
|
||||
auto rec = [&aps](formula f)
|
||||
{
|
||||
return remove_x_rec(f, aps);
|
||||
};
|
||||
|
||||
if (!f.is(op::X))
|
||||
return f.map(rec);
|
||||
|
||||
formula c = rec(f[0]);
|
||||
|
||||
std::vector<formula> vo;
|
||||
for (auto i: aps)
|
||||
{
|
||||
// First line
|
||||
std::vector<formula> va1;
|
||||
formula npi = formula::Not(i);
|
||||
va1.push_back(i);
|
||||
va1.push_back(formula::U(i, formula::And({npi, c})));
|
||||
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), npi);
|
||||
va1.push_back(formula::Or({formula::U(j, npi), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va1));
|
||||
// Second line
|
||||
std::vector<formula> va2;
|
||||
va2.push_back(npi);
|
||||
va2.push_back(formula::U(npi, formula::And({i, c})));
|
||||
for (auto j: aps)
|
||||
if (j != i)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::U(formula::Not(j), i);
|
||||
va2.push_back(formula::Or({formula::U(j, i), tmp}));
|
||||
}
|
||||
vo.push_back(formula::And(va2));
|
||||
}
|
||||
// Third line
|
||||
std::vector<formula> va3;
|
||||
for (auto i: aps)
|
||||
{
|
||||
// make sure the arguments of OR are created in a
|
||||
// deterministic order
|
||||
auto tmp = formula::G(formula::Not(i));
|
||||
va3.push_back(formula::Or({formula::G(i), tmp}));
|
||||
}
|
||||
va3.push_back(c);
|
||||
vo.push_back(formula::And(va3));
|
||||
return formula::Or(vo);
|
||||
}
|
||||
}
|
||||
|
||||
formula remove_x(formula f)
|
||||
{
|
||||
if (f.is_syntactic_stutter_invariant())
|
||||
return f;
|
||||
atomic_prop_set aps;
|
||||
atomic_prop_collect(f, &aps);
|
||||
return remove_x_rec(f, aps);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,27 +23,24 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \brief Rewrite a stutter-insensitive formula \a f without
|
||||
/// using the X operator.
|
||||
///
|
||||
/// This function may also be applied to stutter-sensitive formulas,
|
||||
/// but in that case the resulting formula is not equivalent.
|
||||
///
|
||||
/** \verbatim
|
||||
@Article{ etessami.00.ipl,
|
||||
author = {Kousha Etessami},
|
||||
title = {A note on a question of {P}eled and {W}ilke regarding
|
||||
stutter-invariant {LTL}},
|
||||
journal = {Information Processing Letters},
|
||||
volume = {75},
|
||||
number = {6},
|
||||
year = {2000},
|
||||
pages = {261--263}
|
||||
}
|
||||
\endverbatim */
|
||||
SPOT_API
|
||||
formula remove_x(formula f);
|
||||
}
|
||||
/// \brief Rewrite a stutter-insensitive formula \a f without
|
||||
/// using the X operator.
|
||||
///
|
||||
/// This function may also be applied to stutter-sensitive formulas,
|
||||
/// but in that case the resulting formula is not equivalent.
|
||||
///
|
||||
/** \verbatim
|
||||
@Article{ etessami.00.ipl,
|
||||
author = {Kousha Etessami},
|
||||
title = {A note on a question of {P}eled and {W}ilke regarding
|
||||
stutter-invariant {LTL}},
|
||||
journal = {Information Processing Letters},
|
||||
volume = {75},
|
||||
number = {6},
|
||||
year = {2000},
|
||||
pages = {261--263}
|
||||
}
|
||||
\endverbatim */
|
||||
SPOT_API
|
||||
formula remove_x(formula f);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,24 +24,20 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
formula simplify_f_g(formula p)
|
||||
{
|
||||
formula simplify_f_g(formula p)
|
||||
{
|
||||
// 1 U p = Fp
|
||||
if (p.is(op::U) && p[0].is_tt())
|
||||
return formula::F(p[1]);
|
||||
// 0 R p = Gp
|
||||
if (p.is(op::R) && p[0].is_ff())
|
||||
return formula::G(p[1]);
|
||||
// p W 0 = Gp
|
||||
if (p.is(op::W) && p[1].is_ff())
|
||||
return formula::G(p[0]);
|
||||
// p M 1 = Fp
|
||||
if (p.is(op::M) && p[1].is_tt())
|
||||
return formula::F(p[0]);
|
||||
return p.map(simplify_f_g);
|
||||
}
|
||||
|
||||
// 1 U p = Fp
|
||||
if (p.is(op::U) && p[0].is_tt())
|
||||
return formula::F(p[1]);
|
||||
// 0 R p = Gp
|
||||
if (p.is(op::R) && p[0].is_ff())
|
||||
return formula::G(p[1]);
|
||||
// p W 0 = Gp
|
||||
if (p.is(op::W) && p[1].is_ff())
|
||||
return formula::G(p[0]);
|
||||
// p M 1 = Fp
|
||||
if (p.is(op::M) && p[1].is_tt())
|
||||
return formula::F(p[0]);
|
||||
return p.map(simplify_f_g);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,19 +26,16 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Replace <code>true U f</code> and <code>false R g</code> by
|
||||
/// <code>F f</code> and <code>G g</code>.
|
||||
///
|
||||
/// Perform the following rewriting (from left to right):
|
||||
///
|
||||
/// - true U a = F a
|
||||
/// - a M true = F a
|
||||
/// - false R a = G a
|
||||
/// - a W false = G a
|
||||
///
|
||||
SPOT_API formula simplify_f_g(formula f);
|
||||
}
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Replace <code>true U f</code> and <code>false R g</code> by
|
||||
/// <code>F f</code> and <code>G g</code>.
|
||||
///
|
||||
/// Perform the following rewriting (from left to right):
|
||||
///
|
||||
/// - true U a = F a
|
||||
/// - a M true = F a
|
||||
/// - false R a = G a
|
||||
/// - a W false = G a
|
||||
///
|
||||
SPOT_API formula simplify_f_g(formula f);
|
||||
}
|
||||
|
|
|
|||
6421
src/tl/simplify.cc
6421
src/tl/simplify.cc
File diff suppressed because it is too large
Load diff
|
|
@ -26,179 +26,176 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
class ltl_simplifier_options
|
||||
{
|
||||
class ltl_simplifier_options
|
||||
public:
|
||||
ltl_simplifier_options(bool basics = true,
|
||||
bool synt_impl = true,
|
||||
bool event_univ = true,
|
||||
bool containment_checks = false,
|
||||
bool containment_checks_stronger = false,
|
||||
bool nenoform_stop_on_boolean = false,
|
||||
bool reduce_size_strictly = false,
|
||||
bool boolean_to_isop = false,
|
||||
bool favor_event_univ = false)
|
||||
: reduce_basics(basics),
|
||||
synt_impl(synt_impl),
|
||||
event_univ(event_univ),
|
||||
containment_checks(containment_checks),
|
||||
containment_checks_stronger(containment_checks_stronger),
|
||||
nenoform_stop_on_boolean(nenoform_stop_on_boolean),
|
||||
reduce_size_strictly(reduce_size_strictly),
|
||||
boolean_to_isop(boolean_to_isop),
|
||||
favor_event_univ(favor_event_univ)
|
||||
{
|
||||
public:
|
||||
ltl_simplifier_options(bool basics = true,
|
||||
bool synt_impl = true,
|
||||
bool event_univ = true,
|
||||
bool containment_checks = false,
|
||||
bool containment_checks_stronger = false,
|
||||
bool nenoform_stop_on_boolean = false,
|
||||
bool reduce_size_strictly = false,
|
||||
bool boolean_to_isop = false,
|
||||
bool favor_event_univ = false)
|
||||
: reduce_basics(basics),
|
||||
synt_impl(synt_impl),
|
||||
event_univ(event_univ),
|
||||
containment_checks(containment_checks),
|
||||
containment_checks_stronger(containment_checks_stronger),
|
||||
nenoform_stop_on_boolean(nenoform_stop_on_boolean),
|
||||
reduce_size_strictly(reduce_size_strictly),
|
||||
boolean_to_isop(boolean_to_isop),
|
||||
favor_event_univ(favor_event_univ)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
ltl_simplifier_options(int level) :
|
||||
ltl_simplifier_options(false, false, false)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case 3:
|
||||
containment_checks = true;
|
||||
containment_checks_stronger = true;
|
||||
// fall through
|
||||
case 2:
|
||||
synt_impl = true;
|
||||
// fall through
|
||||
case 1:
|
||||
reduce_basics = true;
|
||||
event_univ = true;
|
||||
// fall through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool reduce_basics;
|
||||
bool synt_impl;
|
||||
bool event_univ;
|
||||
bool containment_checks;
|
||||
bool containment_checks_stronger;
|
||||
// If true, Boolean subformulae will not be put into
|
||||
// negative normal form.
|
||||
bool nenoform_stop_on_boolean;
|
||||
// If true, some rules that produce slightly larger formulae
|
||||
// will be disabled. Those larger formulae are normally easier
|
||||
// to translate, so we recommend to set this to false.
|
||||
bool reduce_size_strictly;
|
||||
// If true, Boolean subformulae will be rewritten in ISOP form.
|
||||
bool boolean_to_isop;
|
||||
// Try to isolate subformulae that are eventual and universal.
|
||||
bool favor_event_univ;
|
||||
};
|
||||
|
||||
// fwd declaration to hide technical details.
|
||||
class ltl_simplifier_cache;
|
||||
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Rewrite or simplify \a f in various ways.
|
||||
class SPOT_API ltl_simplifier
|
||||
ltl_simplifier_options(int level) :
|
||||
ltl_simplifier_options(false, false, false)
|
||||
{
|
||||
public:
|
||||
ltl_simplifier(const bdd_dict_ptr& dict = make_bdd_dict());
|
||||
ltl_simplifier(const ltl_simplifier_options& opt,
|
||||
bdd_dict_ptr dict = make_bdd_dict());
|
||||
~ltl_simplifier();
|
||||
switch (level)
|
||||
{
|
||||
case 3:
|
||||
containment_checks = true;
|
||||
containment_checks_stronger = true;
|
||||
// fall through
|
||||
case 2:
|
||||
synt_impl = true;
|
||||
// fall through
|
||||
case 1:
|
||||
reduce_basics = true;
|
||||
event_univ = true;
|
||||
// fall through
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Simplify the formula \a f (using options supplied to the
|
||||
/// constructor).
|
||||
formula simplify(formula f);
|
||||
bool reduce_basics;
|
||||
bool synt_impl;
|
||||
bool event_univ;
|
||||
bool containment_checks;
|
||||
bool containment_checks_stronger;
|
||||
// If true, Boolean subformulae will not be put into
|
||||
// negative normal form.
|
||||
bool nenoform_stop_on_boolean;
|
||||
// If true, some rules that produce slightly larger formulae
|
||||
// will be disabled. Those larger formulae are normally easier
|
||||
// to translate, so we recommend to set this to false.
|
||||
bool reduce_size_strictly;
|
||||
// If true, Boolean subformulae will be rewritten in ISOP form.
|
||||
bool boolean_to_isop;
|
||||
// Try to isolate subformulae that are eventual and universal.
|
||||
bool favor_event_univ;
|
||||
};
|
||||
|
||||
/// Build the negative normal form of formula \a f.
|
||||
/// All negations of the formula are pushed in front of the
|
||||
/// atomic propositions. Operators <=>, =>, xor are all removed
|
||||
/// (calling spot::ltl::unabbreviate_ltl is not needed).
|
||||
///
|
||||
/// \param f The formula to normalize.
|
||||
/// \param negated If \c true, return the negative normal form of
|
||||
/// \c !f
|
||||
formula
|
||||
// fwd declaration to hide technical details.
|
||||
class ltl_simplifier_cache;
|
||||
|
||||
/// \ingroup ltl_rewriting
|
||||
/// \brief Rewrite or simplify \a f in various ways.
|
||||
class SPOT_API ltl_simplifier
|
||||
{
|
||||
public:
|
||||
ltl_simplifier(const bdd_dict_ptr& dict = make_bdd_dict());
|
||||
ltl_simplifier(const ltl_simplifier_options& opt,
|
||||
bdd_dict_ptr dict = make_bdd_dict());
|
||||
~ltl_simplifier();
|
||||
|
||||
/// Simplify the formula \a f (using options supplied to the
|
||||
/// constructor).
|
||||
formula simplify(formula f);
|
||||
|
||||
/// Build the negative normal form of formula \a f.
|
||||
/// All negations of the formula are pushed in front of the
|
||||
/// atomic propositions. Operators <=>, =>, xor are all removed
|
||||
/// (calling spot::unabbreviate_ltl is not needed).
|
||||
///
|
||||
/// \param f The formula to normalize.
|
||||
/// \param negated If \c true, return the negative normal form of
|
||||
/// \c !f
|
||||
formula
|
||||
negative_normal_form(formula f, bool negated = false);
|
||||
|
||||
/// \brief Syntactic implication.
|
||||
///
|
||||
/// Returns whether \a f syntactically implies \a g.
|
||||
///
|
||||
/// This is adapted from
|
||||
/** \verbatim
|
||||
@InProceedings{ somenzi.00.cav,
|
||||
author = {Fabio Somenzi and Roderick Bloem},
|
||||
title = {Efficient {B\"u}chi Automata for {LTL} Formulae},
|
||||
booktitle = {Proceedings of the 12th International Conference on
|
||||
Computer Aided Verification (CAV'00)},
|
||||
pages = {247--263},
|
||||
year = {2000},
|
||||
volume = {1855},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
publisher = {Springer-Verlag}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
bool syntactic_implication(formula f, formula g);
|
||||
/// \brief Syntactic implication with one negated argument.
|
||||
///
|
||||
/// If \a right is true, this method returns whether
|
||||
/// \a f implies !\a g. If \a right is false, this returns
|
||||
/// whether !\a f implies \a g.
|
||||
bool syntactic_implication_neg(formula f, formula g,
|
||||
bool right);
|
||||
/// \brief Syntactic implication.
|
||||
///
|
||||
/// Returns whether \a f syntactically implies \a g.
|
||||
///
|
||||
/// This is adapted from
|
||||
/** \verbatim
|
||||
@InProceedings{ somenzi.00.cav,
|
||||
author = {Fabio Somenzi and Roderick Bloem},
|
||||
title = {Efficient {B\"u}chi Automata for {LTL} Formulae},
|
||||
booktitle = {Proceedings of the 12th International Conference on
|
||||
Computer Aided Verification (CAV'00)},
|
||||
pages = {247--263},
|
||||
year = {2000},
|
||||
volume = {1855},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
publisher = {Springer-Verlag}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
bool syntactic_implication(formula f, formula g);
|
||||
/// \brief Syntactic implication with one negated argument.
|
||||
///
|
||||
/// If \a right is true, this method returns whether
|
||||
/// \a f implies !\a g. If \a right is false, this returns
|
||||
/// whether !\a f implies \a g.
|
||||
bool syntactic_implication_neg(formula f, formula g,
|
||||
bool right);
|
||||
|
||||
/// \brief check whether two formulae are equivalent.
|
||||
///
|
||||
/// This costly check performs up to four translations,
|
||||
/// two products, and two emptiness checks.
|
||||
bool are_equivalent(formula f, formula g);
|
||||
/// \brief check whether two formulae are equivalent.
|
||||
///
|
||||
/// This costly check performs up to four translations,
|
||||
/// two products, and two emptiness checks.
|
||||
bool are_equivalent(formula f, formula g);
|
||||
|
||||
|
||||
/// \brief Check whether \a f implies \a g.
|
||||
///
|
||||
/// This operation is costlier than syntactic_implication()
|
||||
/// because it requires two translation, one product and one
|
||||
/// emptiness check.
|
||||
bool implication(formula f, formula g);
|
||||
/// \brief Check whether \a f implies \a g.
|
||||
///
|
||||
/// This operation is costlier than syntactic_implication()
|
||||
/// because it requires two translation, one product and one
|
||||
/// emptiness check.
|
||||
bool implication(formula f, formula g);
|
||||
|
||||
/// \brief Convert a Boolean formula as a BDD.
|
||||
///
|
||||
/// If you plan to use this method, be sure to pass a bdd_dict
|
||||
/// to the constructor.
|
||||
bdd as_bdd(formula f);
|
||||
/// \brief Convert a Boolean formula as a BDD.
|
||||
///
|
||||
/// If you plan to use this method, be sure to pass a bdd_dict
|
||||
/// to the constructor.
|
||||
bdd as_bdd(formula f);
|
||||
|
||||
/// \brief Clear the as_bdd() cache.
|
||||
///
|
||||
/// Calling this function is recommended before running other
|
||||
/// algorithms that create BDD variables in a more natural
|
||||
/// order. For instance ltl_to_tgba_fm() will usually be more
|
||||
/// efficient if the BDD variables for atomic propositions have
|
||||
/// not been ordered before hand.
|
||||
///
|
||||
/// This also clears the language containment cache.
|
||||
void clear_as_bdd_cache();
|
||||
/// \brief Clear the as_bdd() cache.
|
||||
///
|
||||
/// Calling this function is recommended before running other
|
||||
/// algorithms that create BDD variables in a more natural
|
||||
/// order. For instance ltl_to_tgba_fm() will usually be more
|
||||
/// efficient if the BDD variables for atomic propositions have
|
||||
/// not been ordered before hand.
|
||||
///
|
||||
/// This also clears the language containment cache.
|
||||
void clear_as_bdd_cache();
|
||||
|
||||
/// Return the bdd_dict used.
|
||||
bdd_dict_ptr get_dict() const;
|
||||
/// Return the bdd_dict used.
|
||||
bdd_dict_ptr get_dict() const;
|
||||
|
||||
/// Cached version of spot::ltl::star_normal_form().
|
||||
formula star_normal_form(formula f);
|
||||
/// Cached version of spot::star_normal_form().
|
||||
formula star_normal_form(formula f);
|
||||
|
||||
/// \brief Rewrite a Boolean formula \a f into as an irredundant
|
||||
/// sum of product.
|
||||
///
|
||||
/// This uses a cache, so it is OK to call this with identical
|
||||
/// arguments.
|
||||
formula boolean_to_isop(formula f);
|
||||
/// \brief Rewrite a Boolean formula \a f into as an irredundant
|
||||
/// sum of product.
|
||||
///
|
||||
/// This uses a cache, so it is OK to call this with identical
|
||||
/// arguments.
|
||||
formula boolean_to_isop(formula f);
|
||||
|
||||
/// Dump statistics about the caches.
|
||||
void print_stats(std::ostream& os) const;
|
||||
/// Dump statistics about the caches.
|
||||
void print_stats(std::ostream& os) const;
|
||||
|
||||
private:
|
||||
ltl_simplifier_cache* cache_;
|
||||
// Copy disallowed.
|
||||
ltl_simplifier(const ltl_simplifier&) SPOT_DELETED;
|
||||
void operator=(const ltl_simplifier&) SPOT_DELETED;
|
||||
};
|
||||
}
|
||||
private:
|
||||
ltl_simplifier_cache* cache_;
|
||||
// Copy disallowed.
|
||||
ltl_simplifier(const ltl_simplifier&) SPOT_DELETED;
|
||||
void operator=(const ltl_simplifier&) SPOT_DELETED;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
214
src/tl/snf.cc
214
src/tl/snf.cc
|
|
@ -21,129 +21,125 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
namespace
|
||||
{
|
||||
namespace
|
||||
// E° if bounded=false
|
||||
// E^□ if nounded=true
|
||||
template<bool bounded>
|
||||
class snf_visitor
|
||||
{
|
||||
// E° if bounded=false
|
||||
// E^□ if nounded=true
|
||||
template<bool bounded>
|
||||
class snf_visitor
|
||||
protected:
|
||||
formula result_;
|
||||
snf_cache* cache_;
|
||||
public:
|
||||
snf_visitor(snf_cache* c)
|
||||
: cache_(c)
|
||||
{
|
||||
protected:
|
||||
formula result_;
|
||||
snf_cache* cache_;
|
||||
public:
|
||||
snf_visitor(snf_cache* c)
|
||||
: cache_(c)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
formula visit(formula f)
|
||||
{
|
||||
if (!f.accepts_eword())
|
||||
return f;
|
||||
formula visit(formula f)
|
||||
{
|
||||
if (!f.accepts_eword())
|
||||
return f;
|
||||
|
||||
snf_cache::const_iterator i = cache_->find(f);
|
||||
if (i != cache_->end())
|
||||
return i->second;
|
||||
snf_cache::const_iterator i = cache_->find(f);
|
||||
if (i != cache_->end())
|
||||
return i->second;
|
||||
|
||||
formula out;
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::eword:
|
||||
out = formula::ff();
|
||||
break;
|
||||
case op::Star:
|
||||
if (!bounded)
|
||||
out = visit(f[0]); // Strip the star.
|
||||
else
|
||||
out = formula::Star(visit(f[0]),
|
||||
std::max(unsigned(f.min()), 1U), f.max());
|
||||
break;
|
||||
case op::Concat:
|
||||
if (bounded)
|
||||
{
|
||||
out = f;
|
||||
break;
|
||||
}
|
||||
// Fall through
|
||||
case op::OrRat:
|
||||
case op::AndNLM:
|
||||
// Let F designate expressions that accept [*0],
|
||||
// and G designate expressions that do not.
|
||||
|
||||
// (G₁;G₂;G₃)° = G₁;G₂;G₃
|
||||
// (G₁;F₂;G₃)° = (G₁°);F₂;(G₃°) = G₁;F₂;G₃
|
||||
// because there is nothing to do recursively on a G.
|
||||
//
|
||||
// AndNLM can be dealt with similarly.
|
||||
//
|
||||
// The above cases are already handled by the
|
||||
// accepts_eword() tests at the top of this method. So
|
||||
// we reach this switch, we only have to deal with...
|
||||
//
|
||||
// (F₁;F₂;F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁&F₂&F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁|G₂|F₃)° = (F₁°)|(G₂°)|(F₃°)
|
||||
formula out;
|
||||
switch (f.kind())
|
||||
{
|
||||
case op::eword:
|
||||
out = formula::ff();
|
||||
break;
|
||||
case op::Star:
|
||||
if (!bounded)
|
||||
out = visit(f[0]); // Strip the star.
|
||||
else
|
||||
out = formula::Star(visit(f[0]),
|
||||
std::max(unsigned(f.min()), 1U), f.max());
|
||||
break;
|
||||
case op::Concat:
|
||||
if (bounded)
|
||||
{
|
||||
unsigned s = f.size();
|
||||
std::vector<formula> v;
|
||||
v.reserve(s);
|
||||
for (unsigned pos = 0; pos < s; ++pos)
|
||||
v.emplace_back(visit(f[pos]));
|
||||
out = formula::OrRat(v);
|
||||
out = f;
|
||||
break;
|
||||
}
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::Fusion:
|
||||
case op::Or:
|
||||
case op::And:
|
||||
SPOT_UNREACHABLE();
|
||||
case op::AndRat: // Can AndRat be handled better?
|
||||
case op::FStar: // Can FStar be handled better?
|
||||
out = f;
|
||||
// Fall through
|
||||
case op::OrRat:
|
||||
case op::AndNLM:
|
||||
// Let F designate expressions that accept [*0],
|
||||
// and G designate expressions that do not.
|
||||
|
||||
// (G₁;G₂;G₃)° = G₁;G₂;G₃
|
||||
// (G₁;F₂;G₃)° = (G₁°);F₂;(G₃°) = G₁;F₂;G₃
|
||||
// because there is nothing to do recursively on a G.
|
||||
//
|
||||
// AndNLM can be dealt with similarly.
|
||||
//
|
||||
// The above cases are already handled by the
|
||||
// accepts_eword() tests at the top of this method. So
|
||||
// we reach this switch, we only have to deal with...
|
||||
//
|
||||
// (F₁;F₂;F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁&F₂&F₃)° = (F₁°)|(F₂°)|(F₃°)
|
||||
// (F₁|G₂|F₃)° = (F₁°)|(G₂°)|(F₃°)
|
||||
{
|
||||
unsigned s = f.size();
|
||||
std::vector<formula> v;
|
||||
v.reserve(s);
|
||||
for (unsigned pos = 0; pos < s; ++pos)
|
||||
v.emplace_back(visit(f[pos]));
|
||||
out = formula::OrRat(v);
|
||||
break;
|
||||
}
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::F:
|
||||
case op::G:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::Xor:
|
||||
case op::Implies:
|
||||
case op::Equiv:
|
||||
case op::U:
|
||||
case op::R:
|
||||
case op::W:
|
||||
case op::M:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::Fusion:
|
||||
case op::Or:
|
||||
case op::And:
|
||||
SPOT_UNREACHABLE();
|
||||
case op::AndRat: // Can AndRat be handled better?
|
||||
case op::FStar: // Can FStar be handled better?
|
||||
out = f;
|
||||
break;
|
||||
}
|
||||
|
||||
return (*cache_)[f] = out;
|
||||
}
|
||||
};
|
||||
}
|
||||
return (*cache_)[f] = out;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
formula
|
||||
star_normal_form(formula sere, snf_cache* cache)
|
||||
{
|
||||
snf_visitor<false> v(cache);
|
||||
return v.visit(sere);
|
||||
}
|
||||
|
||||
formula
|
||||
star_normal_form_bounded(formula sere, snf_cache* cache)
|
||||
{
|
||||
snf_visitor<true> v(cache);
|
||||
return v.visit(sere);
|
||||
}
|
||||
formula
|
||||
star_normal_form(formula sere, snf_cache* cache)
|
||||
{
|
||||
snf_visitor<false> v(cache);
|
||||
return v.visit(sere);
|
||||
}
|
||||
|
||||
formula
|
||||
star_normal_form_bounded(formula sere, snf_cache* cache)
|
||||
{
|
||||
snf_visitor<true> v(cache);
|
||||
return v.visit(sere);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,35 +24,31 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
{
|
||||
typedef std::unordered_map<formula, formula> snf_cache;
|
||||
|
||||
typedef std::unordered_map<formula, formula> snf_cache;
|
||||
/// Helper to rewrite a sere in Star Normal Form.
|
||||
///
|
||||
/// This should only be called on children of a Star operator. It
|
||||
/// corresponds to the E° operation defined in the following
|
||||
/// paper.
|
||||
///
|
||||
/** \verbatim
|
||||
@Article{ bruggeman.96.tcs,
|
||||
author = {Anne Br{\"u}ggemann-Klein},
|
||||
title = {Regular Expressions into Finite Automata},
|
||||
journal = {Theoretical Computer Science},
|
||||
year = {1996},
|
||||
volume = {120},
|
||||
pages = {87--98}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
/// \param sere the SERE to rewrite
|
||||
/// \param cache an optional cache
|
||||
SPOT_API formula
|
||||
star_normal_form(formula sere, snf_cache* cache = nullptr);
|
||||
|
||||
/// Helper to rewrite a sere in Star Normal Form.
|
||||
///
|
||||
/// This should only be called on children of a Star operator. It
|
||||
/// corresponds to the E° operation defined in the following
|
||||
/// paper.
|
||||
///
|
||||
/** \verbatim
|
||||
@Article{ bruggeman.96.tcs,
|
||||
author = {Anne Br{\"u}ggemann-Klein},
|
||||
title = {Regular Expressions into Finite Automata},
|
||||
journal = {Theoretical Computer Science},
|
||||
year = {1996},
|
||||
volume = {120},
|
||||
pages = {87--98}
|
||||
}
|
||||
\endverbatim */
|
||||
///
|
||||
/// \param sere the SERE to rewrite
|
||||
/// \param cache an optional cache
|
||||
SPOT_API formula
|
||||
star_normal_form(formula sere, snf_cache* cache = nullptr);
|
||||
|
||||
/// A variant of star_normal_form() for r[*0..j] where j < ω.
|
||||
SPOT_API formula
|
||||
star_normal_form_bounded(formula sere, snf_cache* cache = nullptr);
|
||||
}
|
||||
/// A variant of star_normal_form() for r[*0..j] where j < ω.
|
||||
SPOT_API formula
|
||||
star_normal_form_bounded(formula sere, snf_cache* cache = nullptr);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,232 +22,229 @@
|
|||
|
||||
namespace spot
|
||||
{
|
||||
namespace ltl
|
||||
unabbreviator::unabbreviator(const char* opt)
|
||||
{
|
||||
unabbreviator::unabbreviator(const char* opt)
|
||||
{
|
||||
while (*opt)
|
||||
switch (char c = *opt++)
|
||||
while (*opt)
|
||||
switch (char c = *opt++)
|
||||
{
|
||||
case 'e':
|
||||
re_e_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
case 'F':
|
||||
re_f_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'G':
|
||||
re_g_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'i':
|
||||
re_i_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
case 'M':
|
||||
re_m_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'R':
|
||||
re_r_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'W':
|
||||
re_w_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case '^':
|
||||
re_xor_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown unabbreviation option: ")
|
||||
+ c);
|
||||
}
|
||||
}
|
||||
|
||||
formula unabbreviator::run(formula in)
|
||||
{
|
||||
auto entry = cache_.emplace(in, nullptr);
|
||||
if (!entry.second)
|
||||
return entry.first->second;
|
||||
|
||||
// Skip recursion whenever possible
|
||||
bool no_boolean_rewrite = !re_some_bool_ || in.is_sugar_free_boolean();
|
||||
bool no_f_g_rewrite = !re_some_f_g_ || in.is_sugar_free_ltl();
|
||||
if (no_boolean_rewrite
|
||||
&& (in.is_boolean() || (no_f_g_rewrite && !re_some_other_)))
|
||||
return entry.first->second = in;
|
||||
|
||||
auto rec = [this](formula f)
|
||||
{
|
||||
return this->run(f);
|
||||
};
|
||||
|
||||
formula out = in;
|
||||
if (in.size() > 0)
|
||||
out = in.map(rec);
|
||||
|
||||
switch (out.kind())
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::U:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
break;
|
||||
case op::F:
|
||||
// F f = true U f
|
||||
if (!re_f_)
|
||||
break;
|
||||
out = formula::U(formula::tt(), out[0]);
|
||||
break;
|
||||
case op::G:
|
||||
// G f = false R f
|
||||
// G f = f W false
|
||||
// G f = !F!f
|
||||
// G f = !(true U !f)
|
||||
if (!re_g_)
|
||||
break;
|
||||
if (!re_r_)
|
||||
{
|
||||
case 'e':
|
||||
re_e_ = true;
|
||||
re_some_bool_ = true;
|
||||
out = formula::R(formula::ff(), out[0]);
|
||||
break;
|
||||
}
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(out[0], formula::ff());
|
||||
break;
|
||||
case 'F':
|
||||
re_f_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'G':
|
||||
re_g_ = true;
|
||||
re_some_f_g_ = true;
|
||||
break;
|
||||
case 'i':
|
||||
re_i_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
case 'M':
|
||||
re_m_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'R':
|
||||
re_r_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case 'W':
|
||||
re_w_ = true;
|
||||
re_some_other_ = true;
|
||||
break;
|
||||
case '^':
|
||||
re_xor_ = true;
|
||||
re_some_bool_ = true;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error
|
||||
(std::string("unknown unabbreviation option: ")
|
||||
+ c);
|
||||
}
|
||||
}
|
||||
|
||||
formula unabbreviator::run(formula in)
|
||||
{
|
||||
auto entry = cache_.emplace(in, nullptr);
|
||||
if (!entry.second)
|
||||
return entry.first->second;
|
||||
|
||||
// Skip recursion whenever possible
|
||||
bool no_boolean_rewrite = !re_some_bool_ || in.is_sugar_free_boolean();
|
||||
bool no_f_g_rewrite = !re_some_f_g_ || in.is_sugar_free_ltl();
|
||||
if (no_boolean_rewrite
|
||||
&& (in.is_boolean() || (no_f_g_rewrite && !re_some_other_)))
|
||||
return entry.first->second = in;
|
||||
|
||||
auto rec = [this](formula f)
|
||||
{
|
||||
return this->run(f);
|
||||
};
|
||||
|
||||
formula out = in;
|
||||
if (in.size() > 0)
|
||||
out = in.map(rec);
|
||||
|
||||
switch (out.kind())
|
||||
auto nc = formula::Not(out[0]);
|
||||
if (!re_f_)
|
||||
{
|
||||
out = formula::Not(formula::F(nc));
|
||||
break;
|
||||
}
|
||||
out = formula::Not(formula::U(formula::tt(), nc));
|
||||
break;
|
||||
}
|
||||
case op::Xor:
|
||||
// f1 ^ f2 == !(f1 <-> f2)
|
||||
// f1 ^ f2 == (f1 & !f2) | (f2 & !f1)
|
||||
if (!re_xor_)
|
||||
break;
|
||||
{
|
||||
case op::ff:
|
||||
case op::tt:
|
||||
case op::eword:
|
||||
case op::ap:
|
||||
case op::Not:
|
||||
case op::X:
|
||||
case op::Closure:
|
||||
case op::NegClosure:
|
||||
case op::NegClosureMarked:
|
||||
case op::EConcat:
|
||||
case op::EConcatMarked:
|
||||
case op::UConcat:
|
||||
case op::U:
|
||||
case op::Or:
|
||||
case op::OrRat:
|
||||
case op::And:
|
||||
case op::AndRat:
|
||||
case op::AndNLM:
|
||||
case op::Concat:
|
||||
case op::Fusion:
|
||||
case op::Star:
|
||||
case op::FStar:
|
||||
break;
|
||||
case op::F:
|
||||
// F f = true U f
|
||||
if (!re_f_)
|
||||
break;
|
||||
out = formula::U(formula::tt(), out[0]);
|
||||
break;
|
||||
case op::G:
|
||||
// G f = false R f
|
||||
// G f = f W false
|
||||
// G f = !F!f
|
||||
// G f = !(true U !f)
|
||||
if (!re_g_)
|
||||
break;
|
||||
if (!re_r_)
|
||||
{
|
||||
out = formula::R(formula::ff(), out[0]);
|
||||
break;
|
||||
}
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(out[0], formula::ff());
|
||||
break;
|
||||
}
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_e_)
|
||||
{
|
||||
auto nc = formula::Not(out[0]);
|
||||
if (!re_f_)
|
||||
{
|
||||
out = formula::Not(formula::F(nc));
|
||||
break;
|
||||
}
|
||||
out = formula::Not(formula::U(formula::tt(), nc));
|
||||
break;
|
||||
out = formula::Not(formula::Equiv(f1, f2));
|
||||
}
|
||||
case op::Xor:
|
||||
// f1 ^ f2 == !(f1 <-> f2)
|
||||
// f1 ^ f2 == (f1 & !f2) | (f2 & !f1)
|
||||
if (!re_xor_)
|
||||
break;
|
||||
else
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_e_)
|
||||
{
|
||||
out = formula::Not(formula::Equiv(f1, f2));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto a = formula::And({f1, formula::Not(f2)});
|
||||
auto b = formula::And({f2, formula::Not(f1)});
|
||||
out = formula::Or({a, b});
|
||||
}
|
||||
}
|
||||
break;
|
||||
case op::Implies:
|
||||
// f1 => f2 == !f1 | f2
|
||||
if (!re_i_)
|
||||
break;
|
||||
out = formula::Or({formula::Not(out[0]), out[1]});
|
||||
break;
|
||||
case op::Equiv:
|
||||
// f1 <=> f2 == (f1 & f2) | (!f1 & !f2)
|
||||
if (!re_e_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto nf1 = formula::Not(f1);
|
||||
auto nf2 = formula::Not(f2);
|
||||
auto term1 = formula::And({f1, f2});
|
||||
auto term2 = formula::And({nf1, nf2});
|
||||
out = formula::Or({term1, term2});
|
||||
break;
|
||||
}
|
||||
case op::R:
|
||||
// f1 R f2 = f2 W (f1 & f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | Gf2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !F!f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !(1 U !f2))
|
||||
if (!re_r_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto f12 = formula::And({f1, f2});
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(f2, f12);
|
||||
break;
|
||||
}
|
||||
auto gf2 = formula::G(f2);
|
||||
if (re_g_)
|
||||
gf2 = run(gf2);
|
||||
out = formula::U(f2, formula::Or({f12, out}));
|
||||
break;
|
||||
}
|
||||
case op::W:
|
||||
// f1 W f2 = f2 R (f2 | f1)
|
||||
// f1 W f2 = f1 U (f2 | G f1)
|
||||
// f1 W f2 = f1 U (f2 | !F !f1)
|
||||
// f1 W f2 = f1 U (f2 | !(1 U !f1))
|
||||
if (!re_w_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_r_)
|
||||
{
|
||||
out = formula::R(f2, formula::Or({f2, f1}));
|
||||
break;
|
||||
}
|
||||
auto gf1 = formula::G(f1);
|
||||
if (re_g_)
|
||||
gf1 = rec(gf1);
|
||||
out = formula::U(f1, formula::Or({f2, out}));
|
||||
break;
|
||||
}
|
||||
case op::M:
|
||||
// f1 M f2 = f2 U (g2 & f1)
|
||||
if (!re_m_)
|
||||
break;
|
||||
{
|
||||
auto f2 = out[1];
|
||||
out = formula::U(f2, formula::And({f2, out[0]}));
|
||||
break;
|
||||
auto a = formula::And({f1, formula::Not(f2)});
|
||||
auto b = formula::And({f2, formula::Not(f1)});
|
||||
out = formula::Or({a, b});
|
||||
}
|
||||
}
|
||||
return entry.first->second = out;
|
||||
}
|
||||
break;
|
||||
case op::Implies:
|
||||
// f1 => f2 == !f1 | f2
|
||||
if (!re_i_)
|
||||
break;
|
||||
out = formula::Or({formula::Not(out[0]), out[1]});
|
||||
break;
|
||||
case op::Equiv:
|
||||
// f1 <=> f2 == (f1 & f2) | (!f1 & !f2)
|
||||
if (!re_e_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto nf1 = formula::Not(f1);
|
||||
auto nf2 = formula::Not(f2);
|
||||
auto term1 = formula::And({f1, f2});
|
||||
auto term2 = formula::And({nf1, nf2});
|
||||
out = formula::Or({term1, term2});
|
||||
break;
|
||||
}
|
||||
case op::R:
|
||||
// f1 R f2 = f2 W (f1 & f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | Gf2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !F!f2)
|
||||
// f1 R f2 = f2 U ((f1 & f2) | !(1 U !f2))
|
||||
if (!re_r_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
auto f12 = formula::And({f1, f2});
|
||||
if (!re_w_)
|
||||
{
|
||||
out = formula::W(f2, f12);
|
||||
break;
|
||||
}
|
||||
auto gf2 = formula::G(f2);
|
||||
if (re_g_)
|
||||
gf2 = run(gf2);
|
||||
out = formula::U(f2, formula::Or({f12, out}));
|
||||
break;
|
||||
}
|
||||
case op::W:
|
||||
// f1 W f2 = f2 R (f2 | f1)
|
||||
// f1 W f2 = f1 U (f2 | G f1)
|
||||
// f1 W f2 = f1 U (f2 | !F !f1)
|
||||
// f1 W f2 = f1 U (f2 | !(1 U !f1))
|
||||
if (!re_w_)
|
||||
break;
|
||||
{
|
||||
auto f1 = out[0];
|
||||
auto f2 = out[1];
|
||||
if (!re_r_)
|
||||
{
|
||||
out = formula::R(f2, formula::Or({f2, f1}));
|
||||
break;
|
||||
}
|
||||
auto gf1 = formula::G(f1);
|
||||
if (re_g_)
|
||||
gf1 = rec(gf1);
|
||||
out = formula::U(f1, formula::Or({f2, out}));
|
||||
break;
|
||||
}
|
||||
case op::M:
|
||||
// f1 M f2 = f2 U (g2 & f1)
|
||||
if (!re_m_)
|
||||
break;
|
||||
{
|
||||
auto f2 = out[1];
|
||||
out = formula::U(f2, formula::And({f2, out[0]}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return entry.first->second = out;
|
||||
}
|
||||
|
||||
formula unabbreviate(formula in, const char* opt)
|
||||
{
|
||||
unabbreviator un(opt);
|
||||
return un.run(in);
|
||||
}
|
||||
formula unabbreviate(formula in, const char* opt)
|
||||
{
|
||||
unabbreviator un(opt);
|
||||
return un.run(in);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue