Encoding Formulas and Model Checking¶
pyModelChecking provides a user friendly support for building CTL*, CTL and LTL formulas. Each of these languages corresponds to a pyModelChecking’s sub-module which implements all the classes required to encode the corresponding formulas.
Propositional logic is also supported by pyModelChecking as a shared basis for all the possible temporal logics.
Propositional Logics¶
Propositional logics support is provided by including the
pyModelChecking.language sub-module. This sub-module allows to
represents atomic propositions and Boolean values through the
pyModelChecking.formula.AtomicProposition
and
pyModelChecking.formula.Bool
classes, respectively.
>>> from pyModelChecking.PL import *
>>> AtomicProposition('p')
p
>>> Bool(True)
true
Moreover, the pyModelChecking.PL
sub-module
implements the logic operators \(\land\), \(\lor\), \(\rightarrow\)
and \(\neg\) by mean of the classes
pyModelChecking.PL.And
, pyModelChecking.PL.Or
,
pyModelChecking.PL.Imply
and
pyModelChecking.PL.Not
, respectively. These classes
automatically wrap strings and Boolean values as objects of the classes
pyModelChecking.PL.AtomicProposition
and
pyModelChecking.PL.Bool
, respectively. All cited classes are
subclasses of the class pyModelChecking.PL.Formula
.
>>> And('p', true)
(p and true)
>>> And('p', true, 'p')
(p and true and p)
>>> f = Imply('q','p')
>>> And('p', f, Imply(Not(f), Or('q','s', f)))
(p and (q --> p) and (not (q --> p) --> (q or s or (q --> p))))
>>> Imply('p', 'q', 'p')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes exactly 3 arguments (4 given)
In order to simplify formula encoding, the operators ~, &, and | –i.e.,
pyModelChecking.PL.__not__()
,
pyModelChecking.PL.__and__()
, and
pyModelChecking.PL.__or__()
– were
overwritten to be used as shortcuts to pyModelChecking.PL.Not
,
pyModelChecking.PL.And
, and pyModelChecking.PL.Or
constructors, respectively. At least one of the operator parameters should
be an object of the class pyModelChecking.PL.Formula
.
>>> AtomicProposition('p') & True
(p and true)
>>> True & AtomicProposition('p')
(true and p)
>>> f = 'p' & Bool(True)
>>> f
(p and true)
>>> True & 'p' & Bool(True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'bool' and 'str'
>>> 'p' & Bool(True) & 'p'
((p and true) and p)
>>> ~('p' & Bool(True)) | And(~f,'b')
(not (p and true) or (not (p and true) and b))
For user convenience, the function pyModelChecking.PL.LNot()
is also provided. This function returns a formula that is equivalent to the
logic negation of the parameter and minimises the number of outermost
\(\neg\).
>>> f = Not(Not(Not(And('p',Not('q')))))
>>> f
not not not (p and not q)
>>> LNot(f)
(p and not q)
>>> LNot(Not(f))
not (p and not q)
>>> LNot(LNot(f))
not (p and not q)
Parsing Formulas¶
The module pyModelChecking.PL
also provides a parsing class
pyModelChecking.PL.Parser
for propositional formula.
Its objects read a formula from a string and, when it is possible,
translate it into the corresponding pyModelChecking.PL.Formula
objects.
>>> p = Parser()
>>> p('p and true')
(p and true)
>>> p('(~p and q) --> ((q | p))')
((not p and q) --> (q or p))
A complete description of the parser grammar is contained in class attribute
pyModelChecking.PL.Parser.grammar
>>> print(p.grammar)
s_formula: "true" -> true
| "false" -> false
| a_prop
| "(" s_formula ")"
u_formula: ("not"|"~") u_formula -> not_formula
| "(" b_formula ")"
| s_formula
b_formula: u_formula
| u_formula ( ("or"|"|") u_formula )+ -> or_formula
| u_formula ( ("and"|"&") u_formula )+ -> and_formula
| u_formula ("-->") u_formula -> imply_formula
a_prop: /[a-zA-Z_][a-zA-Z_0-9]*/ -> string
| ESCAPED_STRING -> e_string
formula: b_formula
%import common.ESCAPED_STRING
%import common.WS
%import WS
Temporal Logics Implementation¶
CTL* formulas can be defined by using the
pyModelChecking.CTLS
sub-module.
>>> from pyModelChecking.CTLS import *
Path quantifiers \(A\) and \(E\) as well as temporal operators
\(X\), \(F\), \(G\), \(U\) and \(R\) are provided as
classes (see CTLS sub-module for more details).
As in the case of propositional logics, these classes wrap strings and
Boolean values as objects of the classes
pyModelChecking.CTLS.language.AtomicProposition
and
pyModelChecking.CTLS.language.Bool
, respectively.
>>> phi = A(G(
... Imply(And(Not('Close'),
... 'Start'),
... A(Or(G(Not('Heat')),
... F(Not('Error')))))
... ))
>>> phi
A(G(((not Close and Start) --> A((G(not Heat) or F(not Error))))))
As far as parsing capabilities and siplifying syntax concern,
pyModelChecking.CTLS
has the same facilities
pyModelChecking.PL
had and implements \(CTL*\) specific
version of both class pyModelChecking.CTLS.Parser
and
operators ~, &, and |.
>>> p=Parser()
>>> p('G(not Heat)') | p('A(F(not Error))')
(G(not Heat) or A(F(not Error)))
Model Checking Formulas¶
The sub-module also implements the CTL* model checking and fair model checking algorithms described in [CGP00].
>>> from pyModelChecking import Kripke
>>> K = Kripke(R=[(0, 1), (0, 2), (1, 4), (4, 1), (4, 2), (2, 0),
... (3, 2), (3, 0), (3, 3), (6, 3), (2, 5), (5, 6)],
... L={0: set(), 1: set(['Start', 'Error']), 2: set(['Close']),
... 3: set(['Close', 'Heat']),
... 4: set(['Start', 'Close', 'Error']),
... 5: set(['Start', 'Close']),
... 6: set(['Start', 'Close', 'Heat'])})
>>> modelcheck(K, psi)
set([0, 1, 2, 3, 4, 5, 6])
>>> modelcheck(K, psi, F=[6])
set([])
It is also possible to model check a string representation of a CTL* formula by
either passing an object of the class pyModelChecking.CTLS.Parser
or leaving the remit of creating such an object to the function
pyModelChecking.CTLS.modelcheck()
.
>>> modelcheck(K, psi_str)
set([0, 1, 2, 3, 4, 5, 6])
>>> modelcheck(K, psi_str, parser=parser)
set([0, 1, 2, 3, 4, 5, 6])
Analogous functionality are provided for CTL and LTL
by the sub-modules pyModelChecking.CTL
and
pyModelChecking.LTL
, respectively.