Skip to content
Automata-based monitoring framework for first-order LTL
Scala R Other
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Ltlfo2mon is an (automata-based) monitoring framework for a first-order temporal logic, called LTLFO. It lets you reason about arbitrary traces (i.e., sequences of events), where events are sets of actions that can carry data; for example {login('user1'),login('user2')},{logout('user2')}.

The framework takes formulae specified in LTLFO as input (see Syntax) and generates monitors for them. The monitors then verify whether a provided trace violates or satisfies the specification. The optimised monitoring algorithm (based on Ltl3tools) is part of the FMSD Journal article The ins and outs of first-order runtime verification, whereas the earlier algorithm (based on lbt) is presented in the conference paper From propositional to first-order monitoring at RV'13.

The master branch contains the current version of Ltlfo2mon, and the folder experiments/ the formulae, traces and monitor results for FMSD. To see the version and the experiments for RV'13, please checkout the branch rv2013.


Ltlfo2mon can be used as a command line tool. Running java -jar ltlfo2mon.jar will show you the following options:

ltlfo2mon v1.3
Usage: ltlfo2mon [options] <LTLFO formula> <trace>

 -o <file> | --output <file>
       Write monitor statistics (size, number of submonitors, etc.) to file.
 -p | --progression
       Use progression/formula rewriting as monitor.
 -sa | --sa-monitor
       Use deprecated SA-based monitor (default is optimized SA-based monitor, 
       based on ltl3tools).
 -v | --verbose
       Show monitor's statistics (size, number of submonitors, etc.) after each step.
 -vv | --verbose level 2
       Show monitor's inner-state after each step.
 <LTLFO formula>
       LTLFO formula that gets monitored.
       Monitor reads single trace from stdin.

By default is used the optimised automata-based algorithm, but the arguments --sa-monitor or --progression let you switch to the algorithm from RV'13 or progression/formula rewriting. Note that you need to install Ltl3tools or lbt to use the FMSD or RV'13 algorithm respectively (see Install).

LTLFO formula syntax

φ := ( φ ) | ~ φ | φ /\ φ | φ \/ φ | φ -> φ | φ <-> φ | G φ | F φ | X φ | φ U φ | 
     φ W φ | A (x_1, ...,x_n): p. φ | E (x_1, ..., x_n): p. φ | p(t_1, ..., t_n) | 
     r(t_1, ...., t_n) | true | false

t_1, ..., t_n are terms, i.e., variables, functions f(t_1, ..., t_n) or constants. Functions take terms as input. Ltlfo2mon comes with some predefined functions (e.g., sum(x,y), sub(x,y), mul(x,y) and constants (e.g., pi). To read how to define your own, please read Configure.

The difference between interpreted predicates p (called I-Operators) and uninterpreted predicates r (called U-Operators) is that the former become true by their appearance in the trace, whereas the latter are evaluated by a program or algorithm (and cannot appear in the trace). Therefore, I-Operators, like functions, require the definition of an evaluation algorithm (see Configure). They differ in that the algorithm for I-Operators has to return Boolean. Ltlfo2mon comes with predefined I-Operators, such as eq(x,y), leq(x,y), even(x), odd(x), regex(str, pattern).

Note: U-Operators (like v, w, login in the following examples) don't have to be predefined (as they don't require an evaluation algorithm). The only requirement is that their names are not yet reserved by I-Operators, functions, or variable names.

Also note: The parser recognises string and integers automatically as constants, and defines them accordingly.

All predicate, function, constant and variable names have to be Java identifiers.


echo "{w(2)},{w(100),w(20)},{w(30)}" | java -jar ltlfo2mon.jar "G A x:w.even(x)"

This will return the result:

Result: ? after 3 events.

The parser recognises 1 as an integer constant automatically:

echo "{w(2),v(4)},{w(12),v(7)},{}" | java -jar ltlfo2mon.jar "G A x:w. E y:v.leq(add(x,1),y)"

This will return the result:

Result: ⊥ after 2 events.

The parser recognises 'user\d*' as a string constant automatically:

echo "{login('user1')},{login('user5')},{}" | java -jar ltlfo2mon.jar "G A x:login. regex(x,'user\d*')"

This will return the result:

Result: ? after 3 events.


Custom predicates, functions or constants can be defined in Conf.scala. For example, the following statement adds the definition of the interpreted predicate even(x):

struct.addIoperator("even", (args: Vector[Any]) => args(0).toString.toInt % 2 == 0)

Here, even is the name of the predicate, and (args: Vector[Any]) => args(0).toString.toInt % 2 == 0 is the algorithm to evaluate the truth value of the predicate. It is defined as a function of signature Vector[Any] => Boolean that takes a vector of arguments as input and returns true or false. Note, that predicates and functions are not type-safe: you have to assure that even(x) takes a unary predicate x as input, which has to be an integer, otherwise the monitor will crash or misbehave at runtime. Functions can be defined similar to predicates with addFunct(name: String, interpr: Vector[Any] => Any).

To define a constant with name pi and value 3.14 add:

struct.addConst("pi", 3.14)

To recompile ltlfo2mon.jar after making changes run sbt (requires sbt 0.13.x) in the base-directory of this project and then write assembly and press RETURN:

$ sbt
[info] Loading project definition from ./src/scala/ltlfo2mon/project
[info] Set current project to ltlfo2mon (in build file:./src/scala/ltlfo2mon/)
> assembly
[info] Packaging ./target/scala-2.10/ltlfo2mon.jar ...
[info] Done packaging.
[success] Total time: 4 s, completed Jul 16, 2013 2:56:14 PM

The jar is written to /target/scala-2.10/.


For the optimised algorithm (default) install the Ltl3tools. Then edit the installation directory in and add the script to your PATH.

For the RV'13 algorithm (argument --sa-monitor) install lbt, which converts a linear temporal logic formula to a generalised Büchi automaton. For Debian/Ubuntu you can install it via apt:

apt-get install lbt

Note: No third-party tools required to run progression/formula rewriting (argument -p).


GPLv3 License.

You can’t perform that action at this time.