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:
Alexandre Duret-Lutz 2015-09-28 16:20:53 +02:00
parent 6ded5e75c4
commit cb39210166
137 changed files with 10771 additions and 10919 deletions

17
NEWS
View file

@ -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)

View file

@ -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);

View file

@ -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)

View file

@ -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.

View file

@ -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())

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}

View file

@ -505,7 +505,7 @@ namespace
}
int
process_formula(spot::ltl::formula, const char*, int)
process_formula(spot::formula, const char*, int)
{
SPOT_UNREACHABLE();
}

View file

@ -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,

View file

@ -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,

View file

@ -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);

View file

@ -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

View file

@ -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)
{

View file

@ -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;

View file

@ -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();

View file

@ -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'))

View file

@ -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);
};

View file

@ -139,7 +139,7 @@ namespace
}
int
process_formula(spot::ltl::formula, const char*, int)
process_formula(spot::formula, const char*, int)
{
SPOT_UNREACHABLE();
}

View file

@ -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.";

View file

@ -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());

View file

@ -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());

View file

@ -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)

View file

@ -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;

View file

@ -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 ≡ (ab)→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())

View file

@ -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;

View file

@ -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;

View file

@ -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 " \

View file

@ -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);
}

View file

@ -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>&

View file

@ -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);

View file

@ -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

View file

@ -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);
}
}
}
}

View file

@ -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;
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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);
/// @}
}
/// @}
}

View file

@ -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;

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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.

View file

@ -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;
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}
}

View file

@ -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);
/// @}
}
/// @}
}

View file

@ -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);
}
}

View file

@ -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_;
};
}

View file

@ -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_;
}
}

View file

@ -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_;
};
}

View file

@ -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;
}
}

View file

@ -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();
};
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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()
{
}
};
}
}
};
}

View file

@ -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,

View file

@ -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;
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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_;
};
}

View file

@ -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;
}
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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);
}

File diff suppressed because it is too large Load diff

View file

@ -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);
/// @}
}

File diff suppressed because it is too large Load diff

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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);
}

File diff suppressed because it is too large Load diff

View file

@ -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;
};
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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