There are two ways to load a DiVinE model: from a file or from a cell.

Loading from a file

We will first start with the file version, however because this notebook should also be a self-contained test case, we start by writing a model into a file.

The spot.ltsmin.load function compiles the model using the ltlmin interface and load it. This should work with DiVinE models if divine --LTSmin works, and with Promela models if spins is installed.

Compiling the model creates all several kinds of files. The test1.dve file is converted into a C++ source code test1.dve.cpp which is then compiled into a shared library test1.dve2c. Becauce spot.ltsmin.load() has already loaded this shared library, all those files can be erased. If you do not erase the files, spot.ltsmin.load() will use the timestamps to decide whether the library should be recompiled or not everytime you load the library.

For editing and loading DVE file from a notebook, it is a better to use the %%dve as shown next.

Loading from a notebook cell

The %%dve cell magic implements all of the above steps (saving the model into a temporary file, compiling it, loading it, erasing the temporary files). The variable name that should receive the model (here m) should be indicated on the first line, after %dve.

Working with an ltsmin model

Printing an ltsmin model shows some information about the variables it contains and their types, however the info() methods provide the data in a map that is easier to work with.

To obtain a Kripke structure, call kripke and supply a list of atomic propositions to observe in the model.

If we have an LTL proposition to check, we can convert it into an automaton using spot.translate(), and synchronize that automaton with the Kripke structure using spot.otf_product(). This otf_product() function returns product automaton that builds itself on-the-fly, as needed by whatever algorithm "consumes" it (here the display routine).

If we want to create a model_check function that takes a model and formula, we need to get the list of atomic propositions used in the formula using atomic_prop_collect(). This returns an atomic_prop_set:

Instead of otf_product(x, y).is_empty() we prefer to call !x.intersects(y). There is also x.intersecting_run(y) that can be used to return a counterexample.

This accepting run can be represented as an automaton (the True argument requires the state names to be preserved). This can be more readable.

Saving Kripke structures to some file

For experiments, it is sometime useful to save a Kripke structure in the HOA format. The HOA printer will automatically use state-labels for Kripke structures.

You can load this as a Kripke structure by passing the want_kripke option to spot.automaton(). The type kripke_graph stores the Kripke structure explicitely (like a twa_graph stores an automaton explicitely), so you may want to avoid it for very large modelsand use it only for development.