citreelo 0.2.0

A simple BDD-based symbolic model checker for Computational Tree Logic
Documentation

CITREELO

CI

This is a basic ROBDD-based symbolic model checker for Computational Tree Logic.

This work started as an interpretation of the presentation of CTL symbolic model checking from the course of Roberto Sebastiani.

I use biodivine-lib-bdd as a backend for the ROBDDs.

The supported CTL operators are:

  • &, |, !, =>, <=>, AX, EX, AF, EF, AG, EG, AU, EU

To compute BDDs representing sets of states satisfying CTL formulae, all these operators directly correspond to operations on BDDs i.e., we do not use translation using a minimal set of operators e.g. "AX p -> !EX(!p)".

Concrete syntax

Formulae are written with the usual operator precedences, so that e.g. AG (p => EF q) needs no further parenthesizing. From weakest to strongest binding:

level operators associativity
1 (weakest) <=> left
2 => right
3 | left
4 & left
5 !, AX, EX, AF, EF, AG, EG prefix
6 (strongest) atoms, true, false, (φ), A[φ U ψ], E[φ U ψ]

The prefix operators chain (AG EF p, !AX !p) and bind tighter than the binary connectives: AX p & q reads as (AX p) & q. The until operators use the bracket notation A[φ U ψ] / E[φ U ψ], where φ and ψ are full formulae.

The names of the atomic propositions are defined by the user (by implementing the CtlFormulaParser trait); keywords are matched up to a word boundary, so an atom whose name merely starts with a keyword (e.g. AXE) is not shadowed.

Use parse_complete_ctl_formula to parse a formula: it consumes the whole input and reports syntax errors with their position, rather than silently accepting a prefix of the formula.

Example

Let us consider the following Kripke structure given the set of atomic propositions AP={P,Q}

example Kripke

We have three states:

  • s0 on which only P holds
  • s1 on which only Q holds
  • s2 on which both P and Q hold

Given a CTL formula built over AP, one can determine the subset of {s0,s1,s2} on which the formula holds.

For instance we have:

p             => {s0,s2},
!p            => {s1},
q             => {s1,s2},
!q            => {s0},
p&q           => {s2},
p|q           => {s0,s1,s2},
(!p)&(!q)     => {},
(!p)|(!q)     => {s0,s1},
// ***
EX(p)         => {s0,s2},
EX(q)         => {s0,s1},
EX(p&q)       => {s0},
EX(p&(!q))    => {s2},
EX((!p)&(!q)) => {},
// ***
AX(p)         => {s2},
AX(q)         => {s0,s1},
AX(q&(!p))    => {s1},
AX(p&(!q))    => {s2},
AX(p&q)       => {},