================================================================= 22c:181 Formal Methods in Software Engineering, Spring 2012 Sample solutions for Simple Nodes exercise ================================================================= 1. node SumReset(X : int; Reset : bool) returns (S : int); let S = (if Reset then 0 else (0 -> pre S)) + X; tel 2. node Average(X : int; Reset : bool) returns (Avg : int); var C : int; let C = (if Reset then 0 else (0 -> pre C)) + 1; Avg = SumReset(X, Reset) / C; tel Alternative implementation: node Average(X : int; Reset : bool) returns (Avg : int); let Avg = SumReset(X, Reset) / SumReset(1, Reset); tel 3. Recall the definition of Sofar: node Sofar(X : bool) returns (R : bool); let R = (true -> (pre R)) and X; tel 3.a Sofar(X) and Sofar(Y) is equivalent to Sofar(X and Y). In fact, let n >= 0. (Sofar(X) and Sofar(Y)) is true at time n <=> Sofar(X) is true at time n and Sofar(Y) is true at time n <=> X is true at time 0,1,...,n and Y is true at time 0,1,...,n <=> (X and Y) is true at time 0,1,...,n <=> Sofar(X and Y) is true at time n 3.b Sofar(X) or Sofar(Y) is not equivalent to Sofar(X or Y). Counterexample: X F T ... Y T F ... Sofar(X) F F ... Sofar(Y) T F ... Sofar(X or Y) T T ... Sofar(X) or Sofar(Y) T F ... 4. node HasHappened(X : bool) returns (Y : bool); let Y = (false -> (pre Y)) or X; tel Alternative implementation, using the Sofar operator: node Sofar(X : bool) returns (Y : bool); let Y = (true -> (pre Y)) and X; tel node HasHappened(X : bool) returns (Y : bool); let Y = not Sofar(not X); tel 5. To do what is requested here it is enough to keep count of consecutive occurrences of false in the input X, and output false as long as this count is at most 3 node MaxDistance3(X : bool) returns(Y : bool); var C : int; let C = if X then 0 else (0 -> pre C) + 1 ; Y = C <= 3 ; tel 6. node MaxDistance(X : bool; N : int) returns(Y : bool); var C : int; let C = if X then 0 else (0 -> pre C) + 1 ; Y = C <= N; tel 7. A more precise description of the node MaxDistance would be: MaxDistance gets one Boolean input X and one integer input N, and outputs a boolean Stream Y. The value of Y at instant k is true if and only if k <= N or X was true at least once at instants k-N, k-N+1, ..., k. 8. The code below is actually not correct in the sense that it assumes arbitrary precision integers. In reality, Lustre's int type is a 32-bit integer, which is subject to overflows. However, the observer Positive ignores the possibility of overflows. This is an example of an inaccurate assumption (arbitrary precision integers) about the execution model. As specified in the exercise, Positive simply cannot be implemented in Lustre. Both the specification and the implementation of Positive need to be amended to take overflows into account. node SumReset(X : int; Reset : bool) returns (S : int); let S = (if Reset then 0 else (0 -> pre S)) + X; tel node Average(X : int; Reset : bool) returns (Avg : int); let Avg = SumReset(X, Reset) / SumReset(1, Reset); tel node Positive(X : int; Reset : bool) returns(OK : bool); let OK = Sofar(X > 0) => Average(X, Reset) > 0; tel 9. The same observations as in the previous problem apply here too. node PositiveReset(X : int; Reset : bool) returns(Ok : bool); let Ok = SinceIncl(Reset, X > 0) => Average(X, Reset) > 0; tel 10. node First( X : int ) returns ( a : int ); let a = X -> pre a; tel node HasHappened(X : bool) returns (Y : bool); let Y = (false -> (pre Y)) or X; tel One possible node F with the required property (replace 10 with 20 to get one that does not have the property) node F() returns(Y : int); var preY : int; let preY = -11 -> pre Y; Y = if preY < 10 then preY + 1 else -11; tel node NegPos(X : int) returns (OK : bool); var Y, x : int; let x = First(X); Y = F(); OK = (Y = x and x > 0) => HasHappened(Y = -x); tel