This assignment will be closed on May 06, 2026 (23:59:59).
You must be authenticated to submit your files

CSE308 - Tutorial 6 - CTL Model Checking

Setup

In this lab you will need to install the BDD library from PySMT with the following command:

$ pysmt-install --bdd

Apart from the older dependencies (look at TD1 for reference) in this lab you will need NuSMV (look at TD4 for reference) and additionally the BDD library from PySMT.

IMPORTANT: The BDD installation will not work on MacOS (and not tried on windows), but it does on the linux lab machines.

You can connect via ssh to the machines at polytechnique. Check the Working via ssh on moodle. You can further use the SSH extension to Visual Studio Code to make your life easier (as explained in the page linked above).

After your setup is complete, download and extract the files of the tutorial CSE308-TD6-1-handin.zip. You’ll have a folder called CSE308-TD6-1-handin.

Installing pysmt on the lab machines

Of course, you’ll need to install pysmt on the lab machine. You can follow this guide.

  1. Install anaconda with a recent python distribution (you may check your python vesion, it should be >= 3.10)

    $ wget https://repo.anaconda.com/archive/Anaconda3-2024.02-1-Linux-x86_64.sh
    $ bash Anaconda3-2024.02-1-Linux-x86_64.sh

    Accept the license and take a coffee.

  2. Install the python pysmt package

    $ pip install pysmt

    The command will install pysmt in your home directory.

  3. Install the BDD package and Z3 (the SAT solver that we will use next week)

    $ ~/.local/bin/pysmt-install --bdd
    $ ~/.local/bin/pysmt-install --z3

Evaluation.

You will receive a maximum 20 points, subdivided as follows:

Exercise 1 - Specialized CTL operators

In this exercise you will work on pen and paper and submit your answer in the file ctl.pdf.

In class, we considered CTL formula containing the operators the subformulas \(\mathbf{EX} \Phi, \mathbf{EG} \Phi\), and \(\Phi_1\ \mathbf{U}\ \Phi_2\). While that is sufficient to compute the denotation of a generic CTL formula, you may think of specfic ways of computing the denotation for the remaining operators.

Write the computation of the denotation for the following CTL formulas (in the last two cases you will need to compute a specific fix point):

  1. \(\mathbf{AX}\ \Phi\)

  2. \(\mathbf{AG}\ \Phi\)

  3. \(\mathbf{A}\ (\Phi_1\ \mathbf{U}\ \Phi_2)\)

Exercise 2 - Specifying and verifying CTL properties in SMV

You will work in the SMV file smv/chain.smv.

The file already specifies a simple transition system that increments a variable n from 0 to 255, and then keeps its value at 255. The system has also a transitions from every state n such that n + 1 % 3 = 0 to the the state n + 1 - 3 (0 does not have such transition, since we’re not considering negative numbers).

You will write and verify the following CTL properties in NuSMV. CTL properties in SMV are a Boolean combination of atomic proposition and merge path and temporal quantifiers, which are merged together (i.e., E F p is expressed in NuSMV with a single operator EF merging the path quantifier E and temporal quantifier F (you can see the other operators in the NuSMV manual).

Note that in SMV the until operator is written as A [formula U formula], so it uses square brackets to enclose the until part of the operator (instead of normal round parenthesis). When we’ll switch to Python later the concrete syntax will change to formula AU formula instead (and similarly for the EU operator).

The CTL property you have to write and check are described in natural language in the smv file (you have a placeholder for each one of them, you have to replace TRUE with your interpretation of the formula in CTL).

Check CTL properties with NuSMV. We provided you the file smv/check_ctl.cmd that you can use to call NuSMV to read your model and check all the CTL properties in a non-interactive way (so, you don’t have to write the commands every time). Just run NuSMV as follows:

$ NuSMV -source smv/check_ctl.cmd smv/chain.smv

You can also use the interactive mode:

$ NuSMV -int smv/chain.smv

and then control what to do. You can find the commands you can use in the NuSMV manual.

Exercise 3 - Symbolic CTL model checking

A. Symbolic Transition Systems and BDDs

Symbolic Transition Systems

The class SymbolicTS represents a transition system symbolically using Boolean formulas (it is defined in the file src/mc308/auto/sts.py). You can create a transition system as follows:

V = [Symbol('a'), Symbol('b'))
a,b = V
a_next = get_next(a)
b_next = get_next(b)

# V = {a,b}
# Init := ! a & ! b
# Trans := a' <-> a
ts = SymbolicTS(V, And([Not(a),Not(b)]), And(Iff(a_next,a)))

As usual, we represent Boolean formulas with the PySMT library. Note that you already have functions like get_next to get the variable (symbol) that correspond to a variable after taking a transition, the “primed” version of a variable (clearly, that naming convention is just an arbitrary choice to distinguish variables representing the “current” and the “next” state).

Binary decision diagrams

You will use Binary Decision Diagrams (BDDs) to reason about Boolean formulas (reason means deciding satisfiability, validity, and eliminating quantifiers).

We will see more about BDDs in class next week, but in a nutshell:

We will not implement the BDD operation today, but we will use an existing BDD package and, even more, you will use the class BDDWrapper (src/mc308/bdd/bdd_wrapper.py) that provides you the primitives to work with BDDs (and hides some technical details):

def get_bdd(self, formula):
  ...
def get_formula(self, bdd):
  ...
def And(self, bdd1, bdd2):
  ...
def Or(self, bdd1, bdd2):
  ...
def Not(self, bdd1):
  ...
def Rename(self, bdd, maps):
  ...
def Elim(self, vars_list, bdd):
  ...

get_bdd returns the bdd for a formula, get_formula gets a formula from a BDD, And, Or, Not, performs the logical operations on two BDDs, Rename renames the variables in the BDD, and Elim performs a quantifier elimination.

Image computation with BDDs

You will implement the function:

def get_successors(sts : SymbolicTS, S : BoolFormula) -> BoolFormula:

defined in src/mc308/td6.py.

Given a symbolic transition system and a formula S representing a set of states, computes the set of states \(Img\) such that:

\[s_2 \models Img \text{ iff there exists }\ s_1 \text{ such that } s_1 \models S \text{ and } s_1,s_2' \models T\]

where T is the formula representing the transition relation of the symbolic transition system.

That’s it, the state \(Img\) is called image of the set \(S\) and is the set of all the states that can be reached from S taking the transition T once.

To compute the image symbolically you need to:

(1) “Remove” the quantifiers from this formula:

\[\text{Img}' := \exists v_1,v_2,v_3, \ldots . (S \land T) \]

Intuitively, the formula \(\text{Img}'\) represents all the assignments to \(v_1', v_2', \ldots\) such that there exists an assignment to the variables \(v_1, v_2, \ldots\) (i.e., all the variables of the transition system STS) such that the transition relation T is satisfiable.

Now, to remove the quantifiers (step 1) you will have to use a BDD. The idea is that you can convert a formula to a BDD, perform operations on it, and then convert it back to a formula. Take for example the following code:

w = BDDWrapper()
bdd = w.get_bdd(formula)
bdd = w.and(bdd, w.not(bdd))
result = bdd.get_formula(bdd)

that creates a bdd for a formula, computes the and with it’s negation (using BDDs!), and finally converts back the BDD to a formula.

(2) Rename all the variables \(v_1', v_2', \ldots \in Img'\) to \(v_1, v_2, \ldots\)

You may want to use the function substitute from pysmt to perform the renaming.

B. Denotation and CTL model checking

You will first implement the basic operations of CTL symbolic model checking to compute the denotation of a formula \(\phi\).

Compute EX

You will start with implementing the denotation computation for the path and temporal operators. First, implement the “pre-image” computation function for computing the denotation \([\![ \textbf{EF}\ \phi ]\!]\):

def compute_ex(bdd_wrapper : BDDWrapper,
               ts : SymbolicTS,
               bdd_phi : BDD) -> BDD

Observe that the function takes as input a BDD of the formula \(\phi\) and returns a BDD of the denotation as output (also, in a realistic setting you would not pass a symbolic transition system represented with a formulas but already its BDD representations, to compute them only once).

Compute EG

Implement the function:

def compute_eg(bdd_wrapper : BDDWrapper,
               ts : SymbolicTS,
               bdd_phi : BDD) -> BDD

that computes the denotation \([\![ \textbf{EG}\ \phi ]\!]\).

Here you will need to compute the denotation as a fix-point.

Compute EU

Implement the function:

def compute_eu(bdd_wrapper : BDDWrapper,
               ts : SymbolicTS,
               bdd_phi1 : BDD,
               bdd_phi2 : BDD) -> BDD

that computes the denotation \([\![ \textbf{E}\ (\phi_1\ \mathbf{U} \phi_2) ]\!]\).

Compute the denotation recursively CTL formula

With the above function you can now implement the symbolic computation of the denotation of a CTL formula expressed in existential normal form (only operators EX, EG, EU):

def compute_bdd_denotation(bdd_wrapper : BDDWrapper,
                           ts : SymbolicTS,
                           ctl_formula : CtlFormula) -> BDD

The function above takes as input a ctl formula an returns the BDD representing its denotation.

The function should proceed by induction on the structure of the formula, checking all the possible cases and managing the BDD construction:

Symbolic CTL model checking

Implement the function:

def ctl_mc(ts : SymbolicTS, formula : CtlFormula) -> bool

that checks if \(ts \models formula\).

Submit your work

You’ll have to upload the following files

Upload form is only available when connected
Upload form is only available when connected
Upload form is only available when connected
Upload form is only available when connected