Lecture Notes
Synchronous observers
Software systems are often required to satisfy one or more safety properties. With synchronous reactive systems, a safety property is, essentially, one that is true of the system at all instants. When developing such systems in a language like Lustre, a convenient way to specify safety properties is to use synchronous observers.
These are programs that observe the input and output streams of the program S to be verified, and have a Boolean output stream for each safety property specified for S. The observers are defined so that, for each output stream, the output value is true at any point in the stream if, and only if, the corresponding safety property holds for S at that point.
Note that synchronous observers are not limited to safety properties. For instance, they can be used to check more complex properties such as the equivalence of two programs. They are explained nicely in the first 2 sections of [Halb99].
In class we have seen a few examples of synchronous observer programs:
- Two boolean switches example with their observers
-
Rising edge and
falling edge examples,
with observer
Temporal Combinators
When writing synchronous observers the following temporal operators, defined in temporal.lus, are often useful.
-
Sofar(X) indicates if X has been true from the beginning of
time or not. (simulate)
-
First(X) is a constant stream which has the value that X had
in the first point in time. (simulate)
-
Since(X,Y) is true precisely when X has been true at some point,
and Y has been true since then.
There is an overlapping variant
of Since that is called SinceIncl(X,Y) (simulate Since, simulate SinceIncl).
The following additional examples make use of those combinators:
- Integer switch example
From natural language to propositional logic to Lustre
When formalizing a safety property, the following table may be helpful in translating from natural language.
English | Logic | Lustre |
A and B
A but B |
A ∧ B | A and B |
A if B A when B A whenever B |
B ⇒ A | B => A |
if A, then B
A implies B A forces B |
A ⇒ B | A => B |
only if A, B B only if A |
B ⇒ A | B => A |
A precisely when B
A if and only if B |
B ⇔ A A ⇔ B |
B = A A = B |
A or B
either A or B |
A ⊕ B ("exclusive or", "xor") |
xor |
A or B A unless B |
A ∨ B ("logical or") |
A or B |