revamp the formula hierarchy (montro-patch)

Flatten the formula ltl::formula hiearchy into a single ltl::vnode that
has an enumerator to distinguish the types of node, and a common
interface to access children, update reference counts, etc.  The
ltl::formula class is now a thin wrapper around an ltl::vnode pointer to
keep track of reference counts automatically.  Visitor are not used
anymore; we now have map() and traversor() methods that are more
concise.

This basically fixes #43, but should be followed by some fine tuning
that should now be localized to the formula.hh and formula.cc files.

Some statistics about this patch.  I started working on it on Sep 9, had
a first compiling version two weeks later on Sep 22, and it then took 5
days to fixes the ~70 distincts bugs that were introduced during the
conversion.  About 13200 lines were modified, and one third of those
were removed.

* src/ltlast/formula.cc, src/ltlast/formula.hh: Complete rewrite,
including what was in separate nearby files.
* src/ltlast/allnodes.hh, src/ltlast/atomic_prop.cc,
src/ltlast/atomic_prop.hh, src/ltlast/binop.cc, src/ltlast/binop.hh,
src/ltlast/bunop.cc, src/ltlast/bunop.hh, src/ltlast/constant.cc,
src/ltlast/constant.hh, src/ltlast/multop.cc, src/ltlast/multop.hh,
src/ltlast/unop.cc, src/ltlast/unop.hh, src/ltlvisit/dump.cc,
src/ltlvisit/dump.hh, src/ltlast/predecl.hh: Delete these files.  Their
feature have been merged in formula.hh and formula.cc.
* src/ltlast/visitor.hh, src/ltlvisit/clone.cc, src/ltlvisit/clone.hh,
src/ltlvisit/dump.hh, src/ltlvisit/postfix.cc, src/ltlvisit/postfix.hh:
Delete these files, as we do not use visitors anymore.
* bench/stutter/stutter_invariance_formulas.cc,
bench/stutter/stutter_invariance_randomgraph.cc, doc/org/tut01.org,
doc/org/tut02.org, doc/org/tut10.org, doc/org/tut22.org,
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_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/ltlast/Makefile.am,
src/ltlenv/declenv.cc, src/ltlenv/declenv.hh, src/ltlenv/defaultenv.cc,
src/ltlenv/defaultenv.hh, src/ltlenv/environment.hh,
src/ltlparse/ltlparse.yy, src/ltlparse/public.hh,
src/ltlvisit/Makefile.am, src/ltlvisit/apcollect.cc,
src/ltlvisit/apcollect.hh, src/ltlvisit/contain.cc,
src/ltlvisit/contain.hh, src/ltlvisit/dot.cc, src/ltlvisit/dot.hh,
src/ltlvisit/exclusive.cc, src/ltlvisit/exclusive.hh,
src/ltlvisit/length.cc, src/ltlvisit/length.hh, src/ltlvisit/mark.cc,
src/ltlvisit/mark.hh, src/ltlvisit/mutation.cc,
src/ltlvisit/mutation.hh, src/ltlvisit/nenoform.cc,
src/ltlvisit/nenoform.hh, src/ltlvisit/print.cc, src/ltlvisit/print.hh,
src/ltlvisit/randomltl.cc, src/ltlvisit/randomltl.hh,
src/ltlvisit/relabel.cc, src/ltlvisit/relabel.hh,
src/ltlvisit/remove_x.cc, src/ltlvisit/remove_x.hh,
src/ltlvisit/simpfg.cc, src/ltlvisit/simpfg.hh,
src/ltlvisit/simplify.cc, src/ltlvisit/simplify.hh, src/ltlvisit/snf.cc,
src/ltlvisit/snf.hh, src/ltlvisit/unabbrev.cc, src/ltlvisit/unabbrev.hh,
src/parseaut/parseaut.yy, src/ta/taexplicit.cc, src/ta/tgtaexplicit.cc,
src/taalgos/minimize.cc, src/taalgos/tgba2ta.cc, src/tests/bare.test,
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/isop.test, src/tests/kind.cc, src/tests/length.cc,
src/tests/ltldo.test, src/tests/ltlfilt.test, src/tests/ltlgrind.test,
src/tests/ltlprod.cc, src/tests/ltlrel.cc,
src/tests/parse_print_test.cc, src/tests/parseaut.test,
src/tests/parseerr.test, 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/twagraph.cc, src/tests/utf8.test,
src/twa/acc.cc, 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.cc, src/twa/twa.hh
src/twa/twagraph.cc, src/twa/twagraph.hh, src/twa/twasafracomplement.cc,
src/twaalgos/compsusp.cc, src/twaalgos/compsusp.hh,
src/twaalgos/dtgbasat.cc, src/twaalgos/hoa.cc, src/twaalgos/lbtt.cc,
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/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/ajax/spotcgi.in, wrap/python/spot.py,
wrap/python/spot_impl.i, wrap/python/Makefile.am,
wrap/python/tests/automata-io.ipynb, wrap/python/tests/formulas.ipynb,
wrap/python/tests/ltl2tgba.py, wrap/python/tests/ltlparse.py,
wrap/python/tests/ltlsimple.py, wrap/python/tests/randltl.ipynb: Adjust
to use the new interface.
* src/sanity/style.test: Accept more C++11 patterns.
* NEWS: Mention the change.
This commit is contained in:
Alexandre Duret-Lutz 2015-09-24 19:44:00 +02:00
parent 1628b188fe
commit b77f7e24c3
177 changed files with 8295 additions and 13332 deletions

View file

@ -72,10 +72,9 @@ exceptions.
int main()
{
print_latex_psl(std::cout, spot::ltl::parse_formula("[]<>p0 || <>[]p1")) << '\n';
const spot::ltl::formula* f = spot::ltl::parse_formula("& & G p0 p1 p2");
spot::ltl::formula f = spot::ltl::parse_formula("& & G p0 p1 p2");
print_lbt_ltl(std::cout, f) << '\n';
print_spin_ltl(std::cout, f, true) << '\n';
f->destroy();
return 0;
}
#+END_SRC
@ -90,12 +89,6 @@ syntax the output, and the type of formula they can output. Here we
are only using LTL formulas for demonstration, so those three
functions are OK with that.
Did you notice the calls to =f->destroy()= at the end? The LTL
formula objects are implemented as DAG with sharing of subformulas.
Each (sub)formula is therefore reference counted, and currently this
is done manually by calling =f->clone()= and =f->destroy()= (do not
ever =delete= a formula, always call =f->destroy()=).
We do not recommend using this =parse_formula()= interface because of
the potential formulas (like =f= or =t=) that have different meanings
in the two parsers that are tried.
@ -118,15 +111,10 @@ Here is how to call the infix parser explicitly,:
{
std::string input = "[]<>p0 || <>[]p1";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_infix_psl(input, pel);
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
{
if (f)
f->destroy();
return 1;
}
return 1;
print_latex_psl(std::cout, f) << '\n';
f->destroy();
return 0;
}
#+END_SRC
@ -165,14 +153,14 @@ with the "fixed" formula if you wish. Here is an example:
{
std::string input = "(a U b))";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_infix_psl(input, pel);
spot::ltl::formula f = spot::ltl::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);
if (f == nullptr)
return 1;
print_latex_psl(std::cout, f) << '\n';
f->destroy();
std::cout << "Parsed formula: ";
print_psl(std::cout, f) << '\n';
return 0;
}
#+END_SRC
@ -186,7 +174,7 @@ with the "fixed" formula if you wish. Here is an example:
: ^
: ignoring trailing garbage
:
: a \U b
: Parsed formula: a U b
The formula =f= is only returned as null when the parser really cannot
@ -207,16 +195,11 @@ of =parse_infix_psl()=.
{
std::string input = "& & G p0 p1 p2";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_prefix_ltl(input, pel);
spot::ltl::formula f = spot::ltl::parse_prefix_ltl(input, pel);
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
{
if (f)
f->destroy();
return 1;
}
return 1;
print_lbt_ltl(std::cout, f) << '\n';
print_spin_ltl(std::cout, f, true) << '\n';
f->destroy();
return 0;
}
#+END_SRC
@ -254,15 +237,10 @@ For instance, let's see what happens if a PSL formulas is passed to
{
std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_infix_psl(input, pel);
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
{
if (f)
f->destroy();
return 1;
}
return 1;
print_spin_ltl(std::cout, f) << '\n';
f->destroy();
return 0;
}
#+END_SRC
@ -289,21 +267,15 @@ The first is to simply diagnose non-LTL formulas.
{
std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_infix_psl(input, pel);
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
return 1;
if (!f.is_ltl_formula())
{
if (f)
f->destroy();
return 1;
}
if (!f->is_ltl_formula())
{
f->destroy();
std::cerr << "Only LTL formulas are supported.\n";
return 1;
}
print_spin_ltl(std::cout, f) << '\n';
f->destroy();
return 0;
}
#+END_SRC
@ -314,7 +286,7 @@ equivalent LTL formula. This does not always work, so you need to be
prepared to reject the formula any way. In our example, we are lucky
(maybe because it was carefully chosen...):
#+BEGIN_SRC C++ :results verbatim :exports code
#+BEGIN_SRC C++ :results verbatim :exports both
#include <string>
#include <iostream>
#include "ltlparse/public.hh"
@ -325,28 +297,20 @@ prepared to reject the formula any way. In our example, we are lucky
{
std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_infix_psl(input, pel);
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
{
if (f)
f->destroy();
return 1;
}
if (!f->is_ltl_formula())
return 1;
if (!f.is_ltl_formula())
{
spot::ltl::ltl_simplifier simp;
const formula* g = simp.simplify(f);
f->destroy();
f = g;
f = simp.simplify(f);
}
if (!f->is_ltl_formula())
if (!f.is_ltl_formula())
{
f->destroy();
std::cerr << "Only LTL formulas are supported.\n";
return 1;
}
print_spin_ltl(std::cout, f) << '\n';
f->destroy();
return 0;
}
#+END_SRC

View file

@ -15,9 +15,9 @@ ltlfilt -ps --relabel=pnn --define -f '"Proc@Here" U ("var > 10" | "var < 4")'
#+END_SRC
#+RESULTS:
: #define p0 ((Proc@Here))
: #define p1 ((var < 4))
: #define p2 ((var > 10))
: #define p0 (Proc@Here)
: #define p1 (var < 4)
: #define p2 (var > 10)
: (p0) U ((p1) || (p2))
When is this output interesting, you may ask? It is useful for
@ -34,9 +34,9 @@ rm tmp.defs tmp.ltl
#+RESULTS:
#+begin_example
#define p0 ((Proc@Here))
#define p1 ((var < 4))
#define p2 ((var > 10))
#define p0 (Proc@Here)
#define p1 (var < 4)
#define p2 (var > 10)
never { /* (p0) U ((p1) || (p2))
*/
T0_init:
@ -88,32 +88,26 @@ destructor.
{
std::string input = "\"Proc@Here\" U (\"var > 10\" | \"var < 4\")";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_infix_psl(input, pel);
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
{
if (f)
f->destroy();
return 1;
}
return 1;
spot::ltl::relabeling_map m;
const spot::ltl::formula* g = spot::ltl::relabel(f, spot::ltl::Pnn, &m);
f = spot::ltl::relabel(f, spot::ltl::Pnn, &m);
for (auto& i: m)
{
std::cout << "#define ";
print_psl(std::cout, i.first) << " (";
print_spin_ltl(std::cout, i.second, true) << ")\n";
}
print_spin_ltl(std::cout, g, true) << '\n';
g->destroy();
f->destroy();
print_spin_ltl(std::cout, f, true) << '\n';
return 0;
}
#+END_SRC
#+RESULTS:
: #define p0 ((Proc@Here))
: #define p1 ((var < 4))
: #define p2 ((var > 10))
: #define p0 (Proc@Here)
: #define p1 (var < 4)
: #define p2 (var > 10)
: (p0) U ((p1) || (p2))
@ -135,7 +129,7 @@ ltlfilt -ps --relabel-bool=pnn --define -f '"Proc@Here" U ("var > 10" | "var < 4
#+END_SRC
#+RESULTS:
: #define p0 ((Proc@Here))
: #define p0 (Proc@Here)
: #define p1 ((var < 4) || (var > 10))
: (p0) U (p1)
@ -151,8 +145,8 @@ ltlfilt -ps --relabel-bool=pnn --define -f 'a U (a & b)'
#+END_SRC
#+RESULTS:
: #define p0 ((a))
: #define p1 ((b))
: #define p0 (a)
: #define p1 (b)
: (p0) U ((p0) && (p1))
This "Boolean sub-expression" relabeling is available in Python and

View file

@ -138,18 +138,13 @@ never claim is done via the =print_never_claim= function.
{
std::string input = "[]<>p0 || <>[]p1";
spot::ltl::parse_error_list pel;
const spot::ltl::formula* f = spot::ltl::parse_infix_psl(input, pel);
spot::ltl::formula f = spot::ltl::parse_infix_psl(input, pel);
if (spot::ltl::format_parse_errors(std::cerr, input, pel))
{
if (f)
f->destroy();
return 1;
}
return 1;
spot::translator trans;
trans.set_type(spot::postprocessor::BA);
spot::twa_graph_ptr aut = trans.run(f);
print_never_claim(std::cout, aut) << '\n';
f->destroy();
return 0;
}
#+END_SRC

View file

@ -4,7 +4,6 @@
#+HTML_LINK_UP: tut.html
This example demonstrates how to create an automaton in C++, and then print it.
The interface
#+BEGIN_SRC C++ :results verbatim :exports both
#include <iostream>