Commit b77f7e24 authored by Alexandre Duret-Lutz's avatar Alexandre Duret-Lutz
Browse files

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.
parent 1628b188
...@@ -15,6 +15,24 @@ New in spot 1.99.3a (not yet released) ...@@ -15,6 +15,24 @@ New in spot 1.99.3a (not yet released)
(But dstar2tgba does not offer all the filtering and (But dstar2tgba does not offer all the filtering and
transformations options of autfilt.) transformations options of autfilt.)
* 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.
- 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.
- Visitors have been replaced by member functions such
as map() or traverse(), that take a function (usually
written as a lambda function) and apply it to the
nodes of the tree.
- As a consequence, writing algorithms that manipulate
formula is more friendly, and several functions
algorithms that spanned a few pages have been
reduced to a few lines.
New in spot 1.99.3 (2015-08-26) New in spot 1.99.3 (2015-08-26)
* The CGI script for LTL translation offers a HOA download link * The CGI script for LTL translation offers a HOA download link
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include "twaalgos/stutter.hh" #include "twaalgos/stutter.hh"
#include "twaalgos/dupexp.hh" #include "twaalgos/dupexp.hh"
#include "twaalgos/stats.hh" #include "twaalgos/stats.hh"
#include "ltlast/allnodes.hh"
#include "ltlvisit/apcollect.hh" #include "ltlvisit/apcollect.hh"
#include "ltlvisit/length.hh" #include "ltlvisit/length.hh"
#include "misc/timer.hh" #include "misc/timer.hh"
...@@ -64,14 +63,10 @@ namespace ...@@ -64,14 +63,10 @@ namespace
} }
int int
process_formula(const spot::ltl::formula* f, process_formula(spot::ltl::formula f, const char*, int)
const char*, int)
{ {
const spot::ltl::formula* nf =
spot::ltl::unop::instance(spot::ltl::unop::Not,
f->clone());
spot::twa_graph_ptr a = trans.run(f); spot::twa_graph_ptr a = trans.run(f);
spot::twa_graph_ptr na = trans.run(nf); spot::twa_graph_ptr na = trans.run(spot::ltl::formula::Not(f));
spot::ltl::atomic_prop_set* ap = spot::ltl::atomic_prop_collect(f); spot::ltl::atomic_prop_set* ap = spot::ltl::atomic_prop_collect(f);
bdd apdict = spot::ltl::atomic_prop_collect_as_bdd(f, a); bdd apdict = spot::ltl::atomic_prop_collect_as_bdd(f, a);
...@@ -103,9 +98,6 @@ namespace ...@@ -103,9 +98,6 @@ namespace
prev = res; prev = res;
} }
std::cout << prev << '\n'; std::cout << prev << '\n';
f->destroy();
nf->destroy();
delete ap; delete ap;
return 0; return 0;
} }
......
...@@ -127,6 +127,5 @@ main(int argc, char** argv) ...@@ -127,6 +127,5 @@ main(int argc, char** argv)
break; break;
} }
dict->unregister_all_my_variables(&ap); dict->unregister_all_my_variables(&ap);
spot::ltl::destroy_atomic_prop_set(ap);
return 0; return 0;
} }
...@@ -72,10 +72,9 @@ exceptions. ...@@ -72,10 +72,9 @@ exceptions.
int main() int main()
{ {
print_latex_psl(std::cout, spot::ltl::parse_formula("[]<>p0 || <>[]p1")) << '\n'; 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_lbt_ltl(std::cout, f) << '\n';
print_spin_ltl(std::cout, f, true) << '\n'; print_spin_ltl(std::cout, f, true) << '\n';
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
...@@ -90,12 +89,6 @@ syntax the output, and the type of formula they can output. Here we ...@@ -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 are only using LTL formulas for demonstration, so those three
functions are OK with that. 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 We do not recommend using this =parse_formula()= interface because of
the potential formulas (like =f= or =t=) that have different meanings the potential formulas (like =f= or =t=) that have different meanings
in the two parsers that are tried. in the two parsers that are tried.
...@@ -118,15 +111,10 @@ Here is how to call the infix parser explicitly,: ...@@ -118,15 +111,10 @@ Here is how to call the infix parser explicitly,:
{ {
std::string input = "[]<>p0 || <>[]p1"; std::string input = "[]<>p0 || <>[]p1";
spot::ltl::parse_error_list pel; 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 (spot::ltl::format_parse_errors(std::cerr, input, pel))
{ return 1;
if (f)
f->destroy();
return 1;
}
print_latex_psl(std::cout, f) << '\n'; print_latex_psl(std::cout, f) << '\n';
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
...@@ -165,14 +153,14 @@ with the "fixed" formula if you wish. Here is an example: ...@@ -165,14 +153,14 @@ with the "fixed" formula if you wish. Here is an example:
{ {
std::string input = "(a U b))"; std::string input = "(a U b))";
spot::ltl::parse_error_list pel; 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 // Use std::cout instead of std::cerr because we can only
// show the output of std::cout in this documentation. // show the output of std::cout in this documentation.
(void) spot::ltl::format_parse_errors(std::cout, input, pel); (void) spot::ltl::format_parse_errors(std::cout, input, pel);
if (f == nullptr) if (f == nullptr)
return 1; return 1;
print_latex_psl(std::cout, f) << '\n'; std::cout << "Parsed formula: ";
f->destroy(); print_psl(std::cout, f) << '\n';
return 0; return 0;
} }
#+END_SRC #+END_SRC
...@@ -186,7 +174,7 @@ with the "fixed" formula if you wish. Here is an example: ...@@ -186,7 +174,7 @@ with the "fixed" formula if you wish. Here is an example:
: ^ : ^
: ignoring trailing garbage : ignoring trailing garbage
: :
: a \U b : Parsed formula: a U b
The formula =f= is only returned as null when the parser really cannot The formula =f= is only returned as null when the parser really cannot
...@@ -207,16 +195,11 @@ of =parse_infix_psl()=. ...@@ -207,16 +195,11 @@ of =parse_infix_psl()=.
{ {
std::string input = "& & G p0 p1 p2"; std::string input = "& & G p0 p1 p2";
spot::ltl::parse_error_list pel; 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 (spot::ltl::format_parse_errors(std::cerr, input, pel))
{ return 1;
if (f)
f->destroy();
return 1;
}
print_lbt_ltl(std::cout, f) << '\n'; print_lbt_ltl(std::cout, f) << '\n';
print_spin_ltl(std::cout, f, true) << '\n'; print_spin_ltl(std::cout, f, true) << '\n';
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
...@@ -254,15 +237,10 @@ For instance, let's see what happens if a PSL formulas is passed to ...@@ -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))"; std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::ltl::parse_error_list pel; 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 (spot::ltl::format_parse_errors(std::cerr, input, pel))
{ return 1;
if (f)
f->destroy();
return 1;
}
print_spin_ltl(std::cout, f) << '\n'; print_spin_ltl(std::cout, f) << '\n';
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
...@@ -289,21 +267,15 @@ The first is to simply diagnose non-LTL formulas. ...@@ -289,21 +267,15 @@ The first is to simply diagnose non-LTL formulas.
{ {
std::string input = "{a*;b}<>->(a U (b & GF c))"; std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::ltl::parse_error_list pel; 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 (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"; std::cerr << "Only LTL formulas are supported.\n";
return 1; return 1;
} }
print_spin_ltl(std::cout, f) << '\n'; print_spin_ltl(std::cout, f) << '\n';
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
...@@ -314,7 +286,7 @@ equivalent LTL formula. This does not always work, so you need to be ...@@ -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 prepared to reject the formula any way. In our example, we are lucky
(maybe because it was carefully chosen...): (maybe because it was carefully chosen...):
#+BEGIN_SRC C++ :results verbatim :exports code #+BEGIN_SRC C++ :results verbatim :exports both
#include <string> #include <string>
#include <iostream> #include <iostream>
#include "ltlparse/public.hh" #include "ltlparse/public.hh"
...@@ -325,28 +297,20 @@ prepared to reject the formula any way. In our example, we are lucky ...@@ -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))"; std::string input = "{a*;b}<>->(a U (b & GF c))";
spot::ltl::parse_error_list pel; 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 (spot::ltl::format_parse_errors(std::cerr, input, pel))
{ return 1;
if (f) if (!f.is_ltl_formula())
f->destroy();
return 1;
}
if (!f->is_ltl_formula())
{ {
spot::ltl::ltl_simplifier simp; spot::ltl::ltl_simplifier simp;
const formula* g = simp.simplify(f); f = simp.simplify(f);
f->destroy();
f = g;
} }
if (!f->is_ltl_formula()) if (!f.is_ltl_formula())
{ {
f->destroy();
std::cerr << "Only LTL formulas are supported.\n"; std::cerr << "Only LTL formulas are supported.\n";
return 1; return 1;
} }
print_spin_ltl(std::cout, f) << '\n'; print_spin_ltl(std::cout, f) << '\n';
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
......
...@@ -15,9 +15,9 @@ ltlfilt -ps --relabel=pnn --define -f '"Proc@Here" U ("var > 10" | "var < 4")' ...@@ -15,9 +15,9 @@ ltlfilt -ps --relabel=pnn --define -f '"Proc@Here" U ("var > 10" | "var < 4")'
#+END_SRC #+END_SRC
#+RESULTS: #+RESULTS:
: #define p0 ((Proc@Here)) : #define p0 (Proc@Here)
: #define p1 ((var < 4)) : #define p1 (var < 4)
: #define p2 ((var > 10)) : #define p2 (var > 10)
: (p0) U ((p1) || (p2)) : (p0) U ((p1) || (p2))
When is this output interesting, you may ask? It is useful for When is this output interesting, you may ask? It is useful for
...@@ -34,9 +34,9 @@ rm tmp.defs tmp.ltl ...@@ -34,9 +34,9 @@ rm tmp.defs tmp.ltl
#+RESULTS: #+RESULTS:
#+begin_example #+begin_example
#define p0 ((Proc@Here)) #define p0 (Proc@Here)
#define p1 ((var < 4)) #define p1 (var < 4)
#define p2 ((var > 10)) #define p2 (var > 10)
never { /* (p0) U ((p1) || (p2)) never { /* (p0) U ((p1) || (p2))
*/ */
T0_init: T0_init:
...@@ -88,32 +88,26 @@ destructor. ...@@ -88,32 +88,26 @@ destructor.
{ {
std::string input = "\"Proc@Here\" U (\"var > 10\" | \"var < 4\")"; std::string input = "\"Proc@Here\" U (\"var > 10\" | \"var < 4\")";
spot::ltl::parse_error_list pel; 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 (spot::ltl::format_parse_errors(std::cerr, input, pel))
{ return 1;
if (f)
f->destroy();
return 1;
}
spot::ltl::relabeling_map m; 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) for (auto& i: m)
{ {
std::cout << "#define "; std::cout << "#define ";
print_psl(std::cout, i.first) << " ("; print_psl(std::cout, i.first) << " (";
print_spin_ltl(std::cout, i.second, true) << ")\n"; print_spin_ltl(std::cout, i.second, true) << ")\n";
} }
print_spin_ltl(std::cout, g, true) << '\n'; print_spin_ltl(std::cout, f, true) << '\n';
g->destroy();
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
#+RESULTS: #+RESULTS:
: #define p0 ((Proc@Here)) : #define p0 (Proc@Here)
: #define p1 ((var < 4)) : #define p1 (var < 4)
: #define p2 ((var > 10)) : #define p2 (var > 10)
: (p0) U ((p1) || (p2)) : (p0) U ((p1) || (p2))
...@@ -135,7 +129,7 @@ ltlfilt -ps --relabel-bool=pnn --define -f '"Proc@Here" U ("var > 10" | "var < 4 ...@@ -135,7 +129,7 @@ ltlfilt -ps --relabel-bool=pnn --define -f '"Proc@Here" U ("var > 10" | "var < 4
#+END_SRC #+END_SRC
#+RESULTS: #+RESULTS:
: #define p0 ((Proc@Here)) : #define p0 (Proc@Here)
: #define p1 ((var < 4) || (var > 10)) : #define p1 ((var < 4) || (var > 10))
: (p0) U (p1) : (p0) U (p1)
...@@ -151,8 +145,8 @@ ltlfilt -ps --relabel-bool=pnn --define -f 'a U (a & b)' ...@@ -151,8 +145,8 @@ ltlfilt -ps --relabel-bool=pnn --define -f 'a U (a & b)'
#+END_SRC #+END_SRC
#+RESULTS: #+RESULTS:
: #define p0 ((a)) : #define p0 (a)
: #define p1 ((b)) : #define p1 (b)
: (p0) U ((p0) && (p1)) : (p0) U ((p0) && (p1))
This "Boolean sub-expression" relabeling is available in Python and This "Boolean sub-expression" relabeling is available in Python and
......
...@@ -138,18 +138,13 @@ never claim is done via the =print_never_claim= function. ...@@ -138,18 +138,13 @@ never claim is done via the =print_never_claim= function.
{ {
std::string input = "[]<>p0 || <>[]p1"; std::string input = "[]<>p0 || <>[]p1";
spot::ltl::parse_error_list pel; 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 (spot::ltl::format_parse_errors(std::cerr, input, pel))
{ return 1;
if (f)
f->destroy();
return 1;
}
spot::translator trans; spot::translator trans;
trans.set_type(spot::postprocessor::BA); trans.set_type(spot::postprocessor::BA);
spot::twa_graph_ptr aut = trans.run(f); spot::twa_graph_ptr aut = trans.run(f);
print_never_claim(std::cout, aut) << '\n'; print_never_claim(std::cout, aut) << '\n';
f->destroy();
return 0; return 0;
} }
#+END_SRC #+END_SRC
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#+HTML_LINK_UP: tut.html #+HTML_LINK_UP: tut.html
This example demonstrates how to create an automaton in C++, and then print it. This example demonstrates how to create an automaton in C++, and then print it.
The interface
#+BEGIN_SRC C++ :results verbatim :exports both #+BEGIN_SRC C++ :results verbatim :exports both
#include <iostream> #include <iostream>
......
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2011, 2012, 2014 Laboratoire de Recherche et Développement // Copyright (C) 2011, 2012, 2014, 2015 Laboratoire de Recherche et
// de l'Epita (LRDE) // Développement de l'Epita (LRDE)
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
// //
...@@ -326,7 +326,7 @@ namespace spot ...@@ -326,7 +326,7 @@ namespace spot
convert_aps(const ltl::atomic_prop_set* aps, convert_aps(const ltl::atomic_prop_set* aps,
const spins_interface* d, const spins_interface* d,
bdd_dict_ptr dict, bdd_dict_ptr dict,
const ltl::formula* dead, ltl::formula dead,
prop_set& out) prop_set& out)
{ {
int errors = 0; int errors = 0;
...@@ -359,7 +359,7 @@ namespace spot ...@@ -359,7 +359,7 @@ namespace spot
if (*ap == dead) if (*ap == dead)
continue; continue;
std::string str = (*ap)->name(); const std::string& str = ap->ap_name();
const char* s = str.c_str(); const char* s = str.c_str();
// Skip any leading blank. // Skip any leading blank.
...@@ -602,7 +602,7 @@ namespace spot ...@@ -602,7 +602,7 @@ namespace spot
public: public:
spins_kripke(const spins_interface* d, const bdd_dict_ptr& dict, spins_kripke(const spins_interface* d, const bdd_dict_ptr& dict,
const spot::prop_set* ps, const ltl::formula* dead, const spot::prop_set* ps, ltl::formula dead,
int compress) int compress)
: kripke(dict), : kripke(dict),
d_(d), d_(d),
...@@ -646,12 +646,12 @@ namespace spot ...@@ -646,12 +646,12 @@ namespace spot
// appropriately. ALIVE_PROP is the bdd that should be ANDed // appropriately. ALIVE_PROP is the bdd that should be ANDed
// to all transitions leaving a live state, while DEAD_PROP should // to all transitions leaving a live state, while DEAD_PROP should
// be ANDed to all transitions leaving a dead state. // be ANDed to all transitions leaving a dead state.
if (dead == ltl::constant::false_instance()) if (dead.is_false())
{ {
alive_prop = bddtrue; alive_prop = bddtrue;
dead_prop = bddfalse; dead_prop = bddfalse;
} }
else if (dead == ltl::constant::true_instance()) else if (dead.is_true())
{ {
alive_prop = bddtrue; alive_prop = bddtrue;
dead_prop = bddtrue; dead_prop = bddtrue;
...@@ -1016,7 +1016,7 @@ namespace spot ...@@ -1016,7 +1016,7 @@ namespace spot
kripke_ptr kripke_ptr
load_ltsmin(const std::string& file_arg, const bdd_dict_ptr& dict, load_ltsmin(const std::string& file_arg, const bdd_dict_ptr& dict,
const ltl::atomic_prop_set* to_observe, const ltl::atomic_prop_set* to_observe,
const ltl::formula* dead, int compress, bool verbose) const ltl::formula dead, int compress, bool verbose)
{ {
std::string file; std::string file;
if (file_arg.find_first_of("/\\") != std::string::npos) if (file_arg.find_first_of("/\\") != std::string::npos)
......
// -*- coding: utf-8 -*- // -*- coding: utf-8 -*-
// Copyright (C) 2011, 2013, 2014 Laboratoire de Recherche et // Copyright (C) 2011, 2013, 2014, 2015 Laboratoire de Recherche et
// Developpement de l'Epita (LRDE) // Developpement de l'Epita (LRDE)
// //
// This file is part of Spot, a model checking library. // This file is part of Spot, a model checking library.
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
#include "kripke/kripke.hh" #include "kripke/kripke.hh"
#include "ltlvisit/apcollect.hh" #include "ltlvisit/apcollect.hh"
#include "ltlast/constant.hh"
namespace spot namespace spot
{ {
...@@ -59,6 +58,6 @@ namespace spot ...@@ -59,6 +58,6 @@ namespace spot
SPOT_API kripke_ptr SPOT_API kripke_ptr
load_ltsmin(const std::string& file, const bdd_dict_ptr& dict, load_ltsmin(const std::string& file, const bdd_dict_ptr& dict,
const ltl::atomic_prop_set* to_observe, const ltl::atomic_prop_set* to_observe,
const ltl::formula* dead = ltl::constant::true_instance(), ltl::formula dead = ltl::formula::tt(),
int compress = 0, bool verbose = true); int compress = 0, bool verbose = true);
} }
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "ltsmin.hh" #include "ltsmin.hh"
#include "twaalgos/dot.hh" #include "twaalgos/dot.hh"
#include "ltlenv/defaultenv.hh" #include "ltlenv/defaultenv.hh"
#include "ltlast/allnodes.hh"
#include "ltlparse/public.hh" #include "ltlparse/public.hh"
#include "twaalgos/translate.hh" #include "twaalgos/translate.hh"
#include "twaalgos/emptiness.hh" #include "twaalgos/emptiness.hh"
...@@ -163,16 +162,16 @@ checked_main(int argc, char **argv) ...@@ -163,16 +162,16 @@ checked_main(int argc, char **argv)
spot::emptiness_check_instantiator_ptr echeck_inst = nullptr; spot::emptiness_check_instantiator_ptr echeck_inst = nullptr;
int exit_code = 0; int exit_code = 0;
spot::postprocessor post; spot::postprocessor post;
const spot::ltl::formula* deadf = nullptr; spot::ltl::formula deadf = nullptr;
const spot::ltl::formula* f = nullptr; spot::ltl::formula f = nullptr;
if (!dead || !strcasecmp(dead, "true")) if (!dead || !strcasecmp(dead, "true"))
{ {