(* CS:5810 Formal Methods in Software Engineering Fall 2020 Lustre Exercises *) (* The current value of isEven(n) is true iff the current value of n is even *) node isEven (n: int) returns (b: bool); let b = (n mod 2 = 0); tel (* The current value of onlyEven(n) is n if n is even and is 0 otherwise *) node onlyEven (x: int) returns (x: int); let Y = if isEven(x) then x else 0; tel (* EvensFrom(x) contains, in increasing order, all even numbers greater than the first value of x *) node EvensFrom (x: int) returns (e: int); let e = (if isEven(x) then x + 2 else x + 1) -> 2 + pre e; tel -- s(_) = 1,2,3,3,3,3,... -- note: input is irrelevant node s (_: bool) returns (x: int); let x = 1 -> if pre x < 3 then pre x + 1 else 3; tel -- more compact version of s node s1 (_: bool) returns (x: int); let x = 1 -> pre (2 -> 3); tel -- (2 -> 3) = 2, 3, 3, 3, ... -- pre (2 -> 3) = //, 2, 3, 3, ... -- x = 1, 2, 3, 3, ... -- Observer node that returns true iff s(b) is the same as s1(b) node obs_s(b: bool) returns (OK: bool); let OK = s(b) = s1(b); tel -- Y = 2, 3, 3, 3, 3, 3, 3, ... -- pre Y = //, 2, 3, 3, ... -- x = 1, 2, 3, 3, 3, 3, ... (* The current value of Sum(x) is the sum of all values of x up to now *) node Sum (x: int) returns (s: int); let s = x -> x + pre s; tel (* 0 1 2 3 4 5 ... ------------------------------- x = 5, 3, -1, 2, 7, 8, ... s = 5, 8, 7, 9, 16, 24, ... *) (* For any boolean stream b, fact(b) is the stream containing all the factorial numbers in increasing order. *) node fact (_: bool) returns (f: int); var n: int; let n = 0 -> pre n + 1; f = 1 -> n * pre f; tel (* Alternate(x) starts at x_0, the initial value of x, and keeps alternating between the current value of x and x_0 *) node Alternate (x: int) returns (y: int); var x_0: int; b: bool; let x_0 = x -> pre x_0; b = true -> not pre b; y = if b then x_0 else x; tel (* Count(reset, pause) starts at 0, and keeps increasing by 1 until reset or stop is true. In the first case it goes back to 0. In the second one, it stays the same (as long as stop is true) *) node Count( reset, pause : bool ) returns ( c : int ); let c = if reset then 0 else if pause then 0 -> pre c else 0 -> pre c + 1; tel (* First(x) is a constant stream whose value is the first value of x. *) node First (x: int) returns (fx: int); let fx = x -> pre fx; tel (* Counter(x, reset) starts at x and keeps increasing by 1 until reset is true, in which case it restarts with the initial value of x *) node Counter (x: int; reset: bool) returns (c: int); let c = if reset then First(x) else x -> pre c + 1; tel node N(I, x: int) returns (Z: int); let Z = if I > 0 then I + 2 else I + x; tel -- prove that the node N above ignores its second input x -- if I is alway positive node ReqN(I, x1, x2: int) returns (P: bool); let -- constrain I to be always positive -- but let x1 and x2 be arbitrary (and arbitrarily different) assert I > 0; -- P holds iff for arbitrarily different second inputs N still returns -- the same output P = N(I,x1) = N(I,x2); -- %MAIN -- %PROPERTY P; tel -- What happens if you remove the assert statement? -- switch(On,Off) is initially false and -- raises (false to true) if On is true, and -- falls (true to false) if Off is true node switch( On,Off: bool) returns (s: bool); let -- very verbose definition -- s = false -> if On=true then true else if Off=true then false else pre s; -- less verbose definition -- s = false -> if (pre s) = false then On else not Off; -- better definition s = s = false -> if (pre s) then not Off else On; tel ------------------------------------------------------------------ -- Sofar(x) is true at any point iff x has been true from -- the beginning until that point node Sofar( x : bool ) returns ( Y : bool ); let Y = x -> (x and (pre Y)); tel --------------------------------------------------------- -- Since(x,Y) is true precisely when x has been true -- at some point, and Y has been continuously true -- afterwards node Since( x, Y : bool ) returns ( SincexY : bool ); let SincexY = x or (Y and (false -> pre SincexY)); tel -- SincexY = x or (Y and (false -> pre SincexY)); ------------------------------------------------------------------ -- SinceIncl(x,Y) is true iff x has been true at some point, -- and Y has been continuously true from then on. -- node SinceIncl( x, Y : bool ) returns ( SincexY : bool ); --let --tel -- SincexY = Y and (x or (false -> pre SincexY)); ----------------------------------------------------------------- -- boolean Switch -- -- Model a switch with two buttons, Set and Reset. -- Pressing Set turns the switch on. -- Pressing Reset turns the switch off -- If Set and Reset are initially both unpressed, -- the initial position of the switch is determined by -- a third signal, Init node Switch( Set, Reset, Init : bool ) returns ( x : bool ); let x = if Set then true else if Reset then false else (Init -> pre x); tel node Switch2( Set, Reset, Init : bool ) returns ( x : bool ); let x = if Reset then false else if Set then true else (Init -> pre x); tel node Switch3( Set, Reset, Init : bool ) returns ( x : bool ); let x = Set or (not Reset and (Init -> pre x)) ; tel ------------------------------------------------------------------ -- The following observer expresses 3 safety requirements -- for the first switch. -- node ReqSwitch( Set, Reset, Init : bool ) returns ( R1, R2, R3 : bool ); var x : bool; let x = Switch( Set, Reset, Init ); -- setting turns the switch on R1 = Set => x; -- resetting turns the switch off R2 = Reset => not x; -- doing nothing maintains the previous value R3 = true -> (not Set and not Reset) => x = pre x; -- %MAIN -- %PROPERTY R1; -- %PROPERTY R2; -- %PROPERTY R3; tel -- R1 = (Set => x); -- not Set or x; -- R2 = (not Set and Reset) => not x; -- R3 = true -> ((not Set and not Reset) => x = pre x); ----------------------------------------------------------------- -- We would like to prove that: -- -- "if Set and Reset are never true at the same time, -- then Switch and Switch2 behave in the same way" -- node ReqSwitches( Set, Reset, Init : bool ) returns ( OK : bool ); var x, x2 : bool; let x = Switch ( Set, Reset, Init ); x2 = Switch2( Set, Reset, Init ); OK = Sofar(not (Set and Reset)) => (x = x2); --%MAIN --%PROPERTY OK; tel (* -- OK = not (Set and Reset) => x = x2; OK = Sofar(not (Set and Reset)) => x = x2; tel *) ----------------------------------------------------------------- -- Show that: -- "the Switch node ignores its input Reset when the -- input Set is true" -- -- ("Ignoring" means that the behavior of Switch is exactly the -- same, independent of the value of Reset when Set is true.) -- node SwitchIgnoresReset( Set, Reset, Reset2, Init : bool ) returns ( OK : bool ); let OK = Set => Switch(Set, Reset, Init) = Switch(Set, Reset2, Init); tel ----------------------------------------------------------------- -- Now, we would like to prove that: -- -- R1 - "if the switch is on, -- it stays so until the next reset" -- -- R2 - "if the switch is off, it stays so until the next set" -- -- Equivalently: -- -- R1 - "if we did not reset since the last time we set, -- x is true" -- R2 - "if we did not set since the last time we reset, -- x is false" node ReqSwitchSetIgnoresReset( Set, Reset, Init : bool ) returns ( R1, R2 : bool ); var x : bool; let x = Switch( Set, Reset, Init ); -- "if we did not reset since the last time we set, -- x is true" R1 = -- "if we did not set since the last time we reset, -- x is false" -- R2 = tel *) -- R1 = Since( Set, not Reset ) => x; -- R2 = Since( Reset and not Set, not Set ) => not x; -- ooo -- ------------------==------------------- -- == -- == -- ------------------==------------------- -- ooo node TrafficLight( button : bool ) returns ( Red, Yellow, Green, Walk, DontWalk : bool ); var Phase, prePhase : int; let prePhase = 0 -> pre Phase; Phase = if button then 1 else if 0 < prePhase and prePhase < 10 then prePhase + 1 else 0; Green = Phase = 0; Yellow = Phase = 1; Red = Phase > 1; Walk = 2 < Phase and Phase < 10; DontWalk = not Walk; tel (* node ReqTrafficLight( button : bool ) returns (R1, R2, R3, R4, R5, R6, R7, R8, R9, R10: bool); var CarsAllowed, Red, Yellow, Green, Walk, DontWalk : bool; let (Red, Yellow, Green, Walk, DontWalk) = TrafficLight(button); -- R1: Walk is never on when cars are allowed -- R2: Red and Green are never on at the same time -- R3: at all times one of the tree colored lights is on -- R4: Walk is on only if Red is -- R5: Walk if on iff DontWalk is off -- R6: Red cannot immediately follow Green -- R7: Walk is off if cars were allowed in the previous step -- R8: Cars are not allowed if Walk was on in the previous step -- R9: Yellow is on for at most one step -- R10: Red changes directly to green -- R11: If the button was never pressed the light is Green -- R12: Red is on whenever Walk is -- R13: Yellow can only follow Green -- R14: Pushing the button when Walk is on has immediate effect -- R15: Red is on for at most 9 cycles -- R16: When Red turn on, Walk is still off tel *) (* CarsAllowed = Green or Yellow; R1 = not (CarsAllowed and Walk); R2 = not (Red and Green); R3 = Red or Yellow or Green; R4 = Walk => Red; R5 = Walk xor DontWalk; R6 = true -> not (Red and pre Green); R7 = true -> not (Walk and pre CarsAllowed); R8 = true -> not (CarsAllowed and pre Walk); R9 = true -> not (Yellow and pre Yellow); R10 = true -> (pre Red and not Red) => Green; tel Phase = if button and (false -> pre DontWalk) then Phase = if button and (false -> pre DontWalk) and prePhase = 0 node ParallelCounters (a, b, c: bool) returns (x, y: int); var n1,n2: int; let n1 = 10; n2 = 5; x = 0 -> if (b or c) then 0 else if a and (pre x) < n1 then (pre x) + 1 else pre x; y = 0 -> if c then 0 else if a and (pre y) < n2 then (pre y) + 1 else pre y; -- Properties -- 1) Whenever x reaches n1, y reaches n2 tel ----------------------------------------------------------------- --node IgnoresFirstInput(x, Y, V: int) return(R1: bool); --let -- R1 = N(x, Y) = N(x, V); --tel ----------------------------------------------------------------- -- an integer switch -- -- Model an integer switch with a button and an -- integer input x. -- When the button is pressed the switch takes the value of x -- and maintains it until the next time the button is pressed -- again. -- before the button is pressed for the first time, the value of -- x is 0. node SwitchInt( Set : bool; x : int ) returns ( Y : int ); let Y = if Set then x else (0 -> pre Y); tel ----------------------------------------------------------------- -- Prove that: -- -- "the SwitchInt node ignores its integer input x -- when the input Set is false" node SwitchIgnoresx( Set : bool; x1, x2: int ) returns ( OK : bool ); var Env : bool; let Env = not Set; OK = Env => SwitchInt(Set, x1) = SwitchInt(Set, x2); -- Env = Sofar(Set => x1 = x2); -- OK = Env => SwitchInt(Set,x1) = SwitchInt(Set,x2); tel ----------------------------------------------------------------- -- Prove that: -- -- "Y always has the latest set value of x" -- -- Let us first do a simple version of this: -- -- "If we have not set the switch again since the last time -- the switch was set to 3, then Y must be 3" node ReqSwitchInt_Simple( Set : bool; x : int ) returns ( OK : bool ); var Y : int; let Y = SwitchInt( Set, x ); OK = Since(Set and x = 3, not Set) => Y = 3; tel ----------------------------------------------------------------- -- To prove that: -- -- "Y always has the latest set value of x" -- -- Equivalently, -- -- "For all values a, -- if we have not set the switch again since the last time -- the switch was set to a, then Y must be a" -- node ReqSwitchInt( Set : bool; x : int; A : int ) returns ( OK : bool ); var Y : int; a : int; let a = First( A ); Y = SwitchInt( Set, x ); OK = Since( Set and x = a, not Set ) => Y = a; tel -- HasHappened(x) is true precisely when x has been true -- at least once since the first instant node HasHappened(x : bool) returns (Y : bool); let Y = x or (false -> pre Y); tel ---------------------------------------------------- -- Write an observer that checks the following -- for an integer input stream Y: -- Whenever Y has the positive value x, -- its opposite -x has occurred in Y before -- x is the first value of an additional -- input stream x node NegBefore(Y: int; x : int) returns (OK : bool); var x : int; let x = First(x); OK = (Y = x and x > 0) => HasHappened(Y = -x); tel -- write a simulator for NegBefore, -- a node that feeds to NegBefore a suitable streams -- for Y and x -- We write a node G whose output Y cycles through [-3..3] -- if its integer input x is initially even, and -- cycles through [0..3] otherwise. node Even(x: int) returns (Y: bool); let Y = 2*(x div 2) = x; tel node G(x: int) returns(Y : int); var preY, lb : int; let lb = if Even(First(x)) then -4 else -1; preY = lb -> pre Y; Y = if preY < 3 then preY + 1 else lb + 1; tel node Simul(x: int) returns (OK: bool); var Y: int; let Y = G(x); OK = NegBefore(Y, x); tel *) ----------------------------------------------------------------- -- Show that -- P1 - (Sofar(x) and Sofar(Y)) is equivalent to -- Sofar(x and Y) for all Boolean streams x and Y. -- -- P2 - (Sofar(x) or Sofar(Y)) is equivalent to -- Sofar(x or Y) for all Boolean streams x and Y. node SofarObs (x, Y: bool) returns (P2: bool); let P2 = (Sofar(x) or Sofar(Y)) = Sofar(x or Y); tel *)