This project implements new techniques for the parameterized verification of
disjunctive timed networks (
This repository contains an implementation which, for a
The summary automaton approach is sound and complete for
This implementation will also check for the existence of flooding paths if the
check succeeds. The summary automaton can then be used to verify properties of
the
As of now, the project is in a prototype state. More specifically it currently does not support:
-
parsing an input file of any kind. Instead, a user will have to manually encode the automaton into the project's Python representation (see input format).
-
checking arbitrary properties, only reachability is supported directly. If a user wants to verify other system properties, she can do so by encoding the summary automaton into a different tool supporting verification timed automata, e.g., UPPAAL.
-
output of a summary automaton in a comprehensible format. Currently, summary automata are represented in the internal Python format. A user needs to manually encode them into, for example, the UPPAAL format if she wants to check advanced properties of a system.
This project can be run locally on your machine (see) or using the provided Docker image (see).
Note however, that the project currently can only be used to calculate minimal reachability times and check for the existence of lassos.
To check the properties described in the paper benchmark section, you must install UPPAAL. Note that you will have to download and install UPPAAL yourself. We cannot distribute it nor include it in our Dockerfiles. Please follow the instructions on the UPPAAL website.
Note: To use UPPAAL you will need a license. UPPAAL does provide free licenses for academic use which you have to register for here.
For the benchmarks presented in the paper UPPAAL version
4.1.26-1
has been used.
We will describe how to reproduce the results from the paper in the benchmark section.
This project only requires Python >=3.9
, all other modules are included or
part of the Python standard library. To execute the program, use:
python3 main.py
Alternatively, you can also use the provided Dockerfile. To execute the image, use:
docker run ghcr.io/cispa/verification-disjunctive-time-networks:latest
By default, it will execute the benchmarks described in the paper and output the runtime statistics along with the minimal reach times for each state. If you would like to instead experiment with the program interactively, you can also use:
docker run --entrypoint python -it ghcr.io/cispa/verification-disjunctive-time-networks:latest
to start an interactive Python shell running in the container. You can then, for example, execute the main function using:
exec(open("main.py").read())
The paper presents a small benchmark suite consisting of two benchmark suits:
-
MINREACH Benchmarks: The first suite demonstrates the effectiveness of our
$MINREACH$ algorithm for computing. More details can be found in the $MINREACH$ section. -
Summary Automaton: This set of benchmarks demonstrates the speedup that can be gained by first constructing a summary automaton and then checking properties using this automaton instead of constructing the full cutoff system. More details can be found in section Summary Automaton.
For all benchmarks, we already include the translations to UPPAAL, including the
summary automaton's encoding. Those files can be found in the
benchmarks
directory. The next section will outline how to
use those files.
After installing UPPAAL, the simplest way to execute any benchmark is to use:
verifyta -u -s <path-to-uppaal-xml-file>
This will automatically execute the property checks as described for the individual benchmarks.
When executing main.py
it will first print the statistics for checking minimal
reachability times with the algorithm described in the paper for the systems
System | UPPAAL Cutoff Encoding | Python Encoding |
---|---|---|
Star(4) | star_4.xml | examples_minreach.py |
Star(5) | star_5.xml | examples_minreach.py |
Star(6) | star_6.xml | examples_minreach.py |
To check the same properties in the cutoff system use UPPAAL with the
accordingly named files provided in
./benchmarks/minreach
.
The next part of the output of main.py
will be statistics for the summary
automaton construction for the systems
System | UPPAAL Cutoff Encoding | UPPAAL Summary Automaton Encoding | Python Encoding |
---|---|---|---|
GCS(3) without invariants | gcs_3_without_invariants_cutoff.xml | gcs_3_without_invariants_summaryAT.xml | examples_dtns.py |
GCS(3) with invariants | gcs_3_with_invariants_cutoff.xml | gcs_3_with_invariants_summaryAT.xml | examples_dtns.py |
GCS(4) without invariants | gcs_4_without_invariants_cutoff.xml | gcs_4_without_invariants_summaryAT.xml | examples_dtns.py |
GCS(4) with invariants | gcs_4_with_invariants_cutoff.xml | gcs_4_with_invariants_summaryAT.xml | examples_dtns.py |
To compare the time it takes to check the properties
This section serves as a very brief introduction to the code and the current input format. This can be useful if you would like to construct summary automata for your own examples or reuse parts of the program.
Currently, the gTA definition must be manually encoded into a
Dict
-based representation. Some examples can be found in
./examples/example_dtns.py
. We will explain the
input in the following section. A gTA consist of:
-
A set of locations, encoded as a list of strings:
locations = ["q1", "q2", "q3", "q4"]
-
A set of initial states, encoded as a list of strings:
init_states = ["q1"]
-
Invariants on states, encoded as a Dict mapping from state names to
Constraints
:invariants = { "q1": Constraint("x", "0", Bound.less_equal(1)), "q2": Constraint("y", "0", Bound.unbounded()), "q3": Constraint("x", "0", Bound.unbounded()), "q4": Constraint("x", "0", Bound.unbounded()) }
A
Constraint
is a limit on the difference between clocks, e.g. the first constraint requires the difference between the clockx
and the constantly zero clock0
to be$\leq 1$ . AConstraint
with an unboundedBound
, i.e.$< \infty$ , does not limit the clock valuations. This representation has been designed with Difference Bound Matrices (DBMs) in mind, as they are used in the underlying zone graph exploration. More details can be found in the paper. -
Transitions, encoded as a
Dict
mapping from transition names to the following entries:-
source_loc
: the source location of the transition -
clock_guard
: The clock guard guarding the transition, which needs to be fulfilled to take this transition. Represented as a list ofConstraints
. -
reset_clocks
: The clocks reset when taking the transition are represented as a list of strings. -
loc_guard
: The location guard of the transition, represented as a list of strings. Another process must be in this location in order to take this transition. If this is a disjunction, it can be represented by creating multiple transitions with the different location guards. -
target_loc
: The target location of this transition.
transitions = to_gta_transitions({ "t1": { "source_loc": "q1", "clock_guard": [Constraint("0", "x", Bound.less_equal(-1))], "reset_clocks": ["x"], "loc_guard": "empty", "target_loc": "q1" }, "t2": { "source_loc": "q1", "clock_guard": [Constraint("0", "y", Bound.less_equal(-5))], "reset_clocks": ["y"], "loc_guard": "empty", "target_loc": "q2" }, "t3": { "source_loc": "q1", "clock_guard": [Constraint("y", "0", Bound.unbounded())], "reset_clocks": [], "loc_guard": "q2", "target_loc": "q3" } })
To convert this representation into the internal transition type use the function
to_gta_transitions
defined in theGTA
module. -
-
A list of clocks appearing in the gTA (the name
"0"
is reserved for the constantly zero clock). By default, the gTA will assume a single clock named"x"
.clocks = ["x", "y"]
Then a gTA object can be constructed using
GTA(locations, init_states, transitions, invariants, clocks)
.
To construct a summary automaton from a gTA, you can construct an object of
either DTNMinus
or DTNWithInv
. DTNMinus
should be used with gTAs that
belong to the
DTNWithInv
should be used only with gTAs with a single clock, but allows for
invariants in states appearing in location guards.
Both classes take an object of type GTA
as input and provide you with the
methods get_min_reach_time()
and get_summary_automaton()
. Where
get_min_reach_time()
will return a Dict providing you with the minimal global
reach time for each location and get_summary_automaton()
will return a tuple
with the summary automaton (a GTA
without location guards) and a Dict
mapping
locations to the DBM describing the zone with the minimal global clock valuation
for that location.
An output format has not been implemented yet. You will have to use the encoding of the summary automaton and translate it manually to the desired output format.
You can use the print_min_reach_times()
to obtain the minimal reachability
times for each state in the
We have already translated the systems used in the presented benchmarks to UPPAAL, more details can be found in the "Benchmarks" section.