|
| 1 | +----------------------------- MODULE CountDown ----------------------------- |
| 2 | +(***************************************************************************) |
| 3 | +(* Example of a counter that counts down from N to 0, together with a *) |
| 4 | +(* liveness proof showing that it will eventually reach 0. *) |
| 5 | +(* *) |
| 6 | +(* Contributed by Andreas Recke. *) |
| 7 | +(***************************************************************************) |
| 8 | +EXTENDS Naturals, TLC, TLAPS, NaturalsInduction |
| 9 | + |
| 10 | +---- |
| 11 | +\* Input: N is the starting number for the countdown |
| 12 | +CONSTANTS N |
| 13 | + |
| 14 | +\* N must be a natural number |
| 15 | +ASSUME NAssumption == N \in Nat |
| 16 | + |
| 17 | +\* Variable i is the running countdown value |
| 18 | +VARIABLES cnt |
| 19 | + |
| 20 | +---- |
| 21 | +\* We define a set S which contains all possible values of the countdown counter |
| 22 | +S == 0..N |
| 23 | + |
| 24 | +---- |
| 25 | +\* Init: i starts at N |
| 26 | +Init == cnt = N |
| 27 | + |
| 28 | +\* Next: if cnt is greater than 0, it will be count down by 1 in the next step |
| 29 | +Next == cnt > 0 /\ cnt' = cnt-1 |
| 30 | + |
| 31 | +\* The complete spec. Important here is the fairness property. Otherwise, we |
| 32 | +\* would not be able to proof that the count down may reach zero, because it |
| 33 | +\* may infinitely stutter at a value larger than zero. |
| 34 | +Spec == Init /\ [][Next]_cnt /\ WF_cnt(Next) |
| 35 | + |
| 36 | +---- |
| 37 | +\* Properties of the algorithm |
| 38 | +Termination == <>(cnt=0) \* count down reaches zero |
| 39 | + |
| 40 | +NextEnabled == cnt > 0 \* for rewriting the ENABLED property to something simpler |
| 41 | + |
| 42 | +TypeInv == cnt \in S |
| 43 | + \* the type correctness property is actually fundamental. |
| 44 | + \* TLA+ values do not have a type, but proofs require it |
| 45 | + |
| 46 | +---- |
| 47 | +\* Theorems |
| 48 | + |
| 49 | +\* this lemma ensures that the type of cnt is always correct |
| 50 | +LEMMA TypeCorrectness == Spec => []TypeInv |
| 51 | +\* From the correct input, ensured by NAssumption, Init leads to a correct type |
| 52 | +<1>1. Init => TypeInv |
| 53 | + BY NAssumption DEF Init, TypeInv, S |
| 54 | +\* The Next transition, here encoded with the "[Next]_cnt" construct, leaves the |
| 55 | +\* TypeInv unchanged in the next state |
| 56 | +<1>2. TypeInv /\ [Next]_cnt => TypeInv' |
| 57 | + BY NAssumption DEF TypeInv, Next, S |
| 58 | +<1>3. QED |
| 59 | + BY <1>1, <1>2, PTL DEF Spec \* standard invariant reasoning |
| 60 | + |
| 61 | +---- |
| 62 | +\* If the input constant N \in Nat, then we can prove that Spec leads to Termination (cnt=0) |
| 63 | +\* We use the DownwardNatInduction rule which actually has the same goal as our algorithm: |
| 64 | +\* start with a number N and prove that if fulfills a requirement P(N), i.e. <>cnt=N |
| 65 | +\* Then just prove that for each n \in 1..N, where P(n) is fulfilled, the requirement P(n-1) |
| 66 | +\* is fulfilled, i.e. <>cnt=(n-1) |
| 67 | +\* This then proves, if cnt can be in 0..N that P(0) will be reached, i.e. <>cnt=0; which |
| 68 | +\* equals Termination |
| 69 | +THEOREM WillReachZero == Spec => Termination |
| 70 | +PROOF |
| 71 | +\* The liveness proof uses an intermediate predicate for downward induction |
| 72 | +\* Note that P(0) just expresses the assertion of the theorem. |
| 73 | +<1> DEFINE P(m) == Spec => <>(cnt = m) |
| 74 | +<1> HIDE DEF P |
| 75 | +<1>2. P(0) |
| 76 | + <2>1. P(N) |
| 77 | +\* Start condition - this is actually obvious. We show that initialization fulfills the first goal |
| 78 | + BY PTL DEF P, Spec, Init |
| 79 | + <2>2. \A n \in 1..N : P(n) => P(n-1) |
| 80 | +\* prove: for all intermediate goals, the next goal will be reached |
| 81 | + <3>1. SUFFICES |
| 82 | + ASSUME NEW n \in 1 .. N |
| 83 | + PROVE Spec /\ <>(cnt = n) => <>(cnt = n-1) |
| 84 | +\* Reformulation replacing the quantifier by a constant |
| 85 | +\* Note that `Spec' remains in the conclusion so that PTL finds only "boxed" hypotheses in the QED step |
| 86 | + BY DEF P |
| 87 | + <3>2. (cnt=n) /\ [Next]_cnt => (cnt=n)' \/ (cnt=n-1)' |
| 88 | + BY DEF Next |
| 89 | +\* WF1 rule, step 1 |
| 90 | + <3>3. (cnt=n) /\ <<Next>>_cnt => (cnt=n-1)' |
| 91 | + BY DEF Next |
| 92 | +\* WF1 rule, step 2 |
| 93 | + <3>4. (cnt=n) => ENABLED <<Next>>_cnt |
| 94 | + BY ExpandENABLED DEF Next |
| 95 | +\* WF1 rule, step 3 |
| 96 | + <3> QED |
| 97 | + BY <3>1, <3>2, <3>3, <3>4, PTL DEF Spec |
| 98 | +\* Now we can conclude the WF1 rule reasoning |
| 99 | + <2> QED |
| 100 | + BY NAssumption, <2>1, <2>2, DownwardNatInduction, Isa |
| 101 | +\* taking the facts <2>1 and <2>2, downward natural induction works |
| 102 | +<1> QED |
| 103 | + BY <1>2, PTL DEF P, Termination |
| 104 | +\* and finally, we can prove the overall goal to show that the spec/algorithm terminates |
| 105 | + |
| 106 | +============================================================================= |
0 commit comments