In [1]:
import spot
For interactive use, formulas can be entered as text strings and passed to the spot.formula
constructor.
In [2]:
f = spot.formula('p1 U p2 R (p3 & !p4)')
f
Out[2]:
In [3]:
g = spot.formula('{a;b*;c[+]}<>->GFb'); g
Out[3]:
By default the parser recognizes an infix syntax, but when this fails, it tries to read the formula with the LBT syntax:
In [4]:
h = spot.formula('& | a b c'); h
Out[4]:
By default, a formula object is presented using mathjax as above. When a formula is converted to string you get Spot's syntax by default:
In [5]:
str(f)
Out[5]:
If you prefer to print the string in another syntax, you may use the to_str()
method, with an argument that indicates the output format to use. The latex
format assumes that you will the define macros such as \U
, \R
to render all operators as you wish. On the otherhand, the sclatex
(with sc
for self-contained) format hard-codes the rendering of each of those operators: this is typically the output that is used to render formulas using MathJax in a notebook.
In [6]:
for i in ['spot', 'spin', 'lbt', 'wring', 'utf8', 'latex', 'sclatex']:
print("%-10s%s" % (i, f.to_str(i)))
Formulas output via format()
can also use some convenient shorthand to select the syntax:
In [7]:
print("""\
Spin: {0:s}
Spin+parentheses: {0:sp}
Spot (default): {0}
Spot+shell quotes: {0:q}
LBT, right aligned: {0:l:~>40}
LBT, no M/W/R: {0:[MWR]l}""".format(f))
The specifiers that can be used with format
are documented as follows:
In [8]:
help(spot.formula.__format__)
A spot.formula
object has a number of built-in predicates whose value have been computed when the formula was constructed. For instance you can check whether a formula is in negative normal form using is_in_nenoform()
, and you can make sure it is an LTL formula (i.e. not a PSL formula) using is_ltl_formula()
:
In [9]:
f.is_in_nenoform() and f.is_ltl_formula()
Out[9]:
In [10]:
g.is_ltl_formula()
Out[10]:
Similarly, is_syntactic_stutter_invariant()
tells wether the structure of the formula guarranties it to be stutter invariant. For LTL formula, this means the X
operator should not be used. For PSL formula, this function capture all formulas built using the siPSL grammar.
In [11]:
f.is_syntactic_stutter_invariant()
Out[11]:
In [12]:
spot.formula('{a[*];b}<>->c').is_syntactic_stutter_invariant()
Out[12]:
In [13]:
spot.formula('{a[+];b[*]}<>->d').is_syntactic_stutter_invariant()
Out[13]:
spot.relabel
renames the atomic propositions that occur in a formula, using either letters, or numbered propositions:
In [14]:
gf = spot.formula('(GF_foo_) && "a > b" && "proc[2]@init"'); gf
Out[14]:
In [15]:
spot.relabel(gf, spot.Abc)
Out[15]:
In [16]:
spot.relabel(gf, spot.Pnn)
Out[16]:
The AST of any formula can be displayed with show_ast()
. Despite the name, this is not a tree but a DAG, because identical subtrees are merged. Binary operators have their left and right operands denoted with L
and R
, while non-commutative n-ary operators have their operands numbered.
In [17]:
print(g); g.show_ast()
Out[17]:
Any formula can also be classified in the temporal hierarchy of Manna & Pnueli
In [22]:
g.show_mp_hierarchy()
Out[22]:
In [24]:
spot.mp_class(g, 'v')
Out[24]:
In [18]:
f = spot.formula('F(a & X(!a & b))'); f
Out[18]:
Etessami's rule for removing X (valid only in stutter-invariant formulas)
In [19]:
spot.remove_x(f)
Out[19]:
Removing abbreviated operators
In [20]:
f = spot.formula("G(a xor b) -> F(a <-> b)")
spot.unabbreviate(f, "GF^")
Out[20]:
In [21]:
spot.unabbreviate(f, "GF^ei")
Out[21]: