Version 22-4-2009 Constraints on parameters ------------------------- 0 < min <= max 0 < g 0 < t g + t + 2 <= k_0 for all nodes i, j : i =/= j implies tsn[i] =/= tsn[j] for convenience, We assume that in the initial state csn[i]=tsn[i], for some i. 3 <= N <= n <= C For a slots s, predicate TX(s) holds iff some node is transmitting in s. Formally, TX : [0, C-1] --> Bool is defined by TX(s) <=> (exists i : tsn[i]=s) For any slot s, PREV(s) denotes the nearest slot preceding s (cyclically) in which some node is transmitting. Formally, PREV : [0, C-1] --> [0, C-1] is defined by PREV((s+1)%C) = if TX(s) then s else PREV(s) For slots s and t, from(s,t) denotes the (cyclic) distance from s to t: from(s,t) = if s=t then 0 else 1+from((s+1)%C,t) Let D(s)=from(PREV(s),s) Let M = max_s D(s). We claim that - on top of the constraints listed above - necessary and sufficient conditions for correctness are C1 M * k0 * max < ((M+1) * k0 - g - 2) * min C2 (M * k0 - g) * max < (M * k0 - 1) * min C3 (k0 - g - t) * max < (k0 - g - 1) * min Lemma 1. Assume C1 and m <= M. Then m * k0 * max < ((m+1) * k0 -g - 2) * min Proof. C1 can be rewritten to M * k0 * (max - min) < (k0 - g - 2) * min Since m <= M, this implies m * k0 * (max - min) < (k0 - g - 2) * min which can be rewritten again to m * k0 * max < ((m+1) * k0 -g - 2) * min Lemma 2. Assume C2 and m <= M. Then (m * k0 - g) * max < (m * k0 -1) * min Proof. Similar to proof Lemma 1. Formally, correctness is defined in terms of the invariant SENDING_i implies csn[i]=csn[j] Local Invariants (for all nodes i) ---------------------------------- INV1(i) 0 <= x_i <= max INV2(i) 0 <= clk[i] < k_0 INV3(i) 0 <= csn[i] < C INV4(i) GO_SEND_i implies x_i=0 INV5(i) GO_SEND_i implies csn[i]=tsn[i] INV6(i) GO_SEND_i implies clk[i] in {g,g+1} INV7(i) SENDING_i implies csn[i]=tsn[i] INV8(i) SENDING_i implies g <= clk[i] < k_0 -t We add the following auxiliary global (history) variables to the model: - a clock y that records the time that has elapsed since the last synchronization (or the beginning of the protocol if there hasn't been any synchronization yet) - variable last records the last slot in which a message has been sent; initially last = -1 For each node i, c[i] gives the number of tick[i] events that have occurred since the last synchronization message (or the start of the protocol): c(i) =def= if last = -1 then clk[i] else if S1_i then 0 else from(last,csn[i])*k0 + clk[i] - g fi fi Invariants ---------- INV9 y >= 0 INV10(i) S1_i implies y <= x_i INV11(i) last = -1 implies S0_i INV12 -1 <= last < C Main invariant -------------- G1(i) y <= c(i)*max +x_i G2(i) c(i)>0 implies y >= (c(i)-1)*min + x_i G3(i) csn[i]=tsn[i] /\ (clk[i] < g \/ GO_SEND_i) implies last =/= csn[i] G3a(i) csn[i]=tsn[i] /\ clk[i]=g implies (GO_SEND_i \/ SENDING_i) G4(i) csn[i]=tsn[i] /\ clk[i] > g implies last = csn[i] G5(i,j) SENDING_i implies csn[i]=csn[j]=last G6(i,j) GO_SEND_i implies csn[i]=csn[j] /\ clk[i]=g G7(i) last = -1 \/ (TX(csn[i] /\ last=csn[i]) \/ last=PREV(csn[i]) G8(i) TX(csn[i]) /\ clk[i] =k0-1 implies last=csn[i] G9(i) S1_i implies clk[i] < k0 -1 /\ last=csn[i] G10(i) c(i) >= 0 G12(i) last=-1 implies csn[i]=0 We write Gj = /\ i Gj(i) We claim that /\_k in [1,12] Gk is inductive relative to INV1-13. Proof: Induction basis =============== G1-G12 trivially hold in the initial state. Now suppose r is a state s.t. r |= G1 /\ .. /\ G12 and r --a--> r' is a transition. We prove r' |= G1 /\ .. /\ G12. CASE 1: a is a delay action =========================== G1(i) and G2(i) are preserved since a single clock variable occurs on both sides of the <= sign. All other assertions only involve discrete var's and are thus trivially preserved. CASE 2: a is a start_message[k] action ====================================== Observe r' |= y=0 /\ x_i >= 0 (effect start_message and INV1) r' |= S1_i /\ last >= 0 (effect start_message ) r' |= c(i) = 0 (def c(i)) Hence r' |= G1(i) r' |= G2(i) r' |= G10(i) r' |= G12(i) We now check that r' |= G3(i) Case 1. i=k. Observe r |= GO_SEND_k r |= clk[k] = g (by r |= G6(k,j) ) r' |= clk[k] = g r' |= SENDING_k Hence r' |= G3(k) Case 2 i =/= k. Observe r.csn[i] = r.csn[k] (by G6(i,k) = r.tsn[k] (by INV5) =/= r.tsn[i] (by assumption on constants tsn) Hence, since start_message action do not change csn, r' |= csn[i] =/= tsn[i] Hence r' |= G3(i) We now check that r' |= G3a(i) Case 1. i=k. Observe r' |= SENDING_k Hence r' |= G3a(i) Case 2. i=/= k. Observe r |= G3a(i) Since start_message[k] modifies none of the variables mentioned in G3a(i), also r' |= G3a(i) Let's check G4(i) and G8(i) together Case 1. i=k By effect of start_message[k], we know r' |= last=csn[k]. Hence r' |= G4(i) and r' |= G8(i). Case 2. i =/= k Observe r.csn[i] = r.csn[k] (by G6(i,k) Hence, since start_message action do not change csn, r' |= csn[i] = csn[k] Moreover, by the effect of start_message[k] r' |= last = csn[k] Hence r' |= last = csn[i] and thus r' |= G4(i) and r' |= G8(i). The proof of G5(i,j) is similar: By G6(k,.) and the precondition of start_message[k] r |= forall l : csn[k]=csn[l] Hence, since start_message action do not change csn, r' |= forall l : csn[k] = csn[l] Moreover, by the effect of start_message[k] r' |= last = csn[k] Hence r' |= csn[i] = csn[j] = last and thus r' |= G5(i,j) Let's do G6(i,j). Observe r |= GO_SEND_k. Hence, by invariant G6(k,j), r |= for all j, csn[k]=csn[j] Hence r |= forall i, j csn[i] = csn[j]. By INV5 and the fact that all tsn's are distinct, we know that for all i =/= k, r |= not GO_SEND_i. Since start_message[k] doesn't modify the control location of processes i =/= k, r' |= not GO_SEND_i By the effect of start_message[k], r' |= SENDING_k Hence r' |= G6(i,j) We consider invariant G7(i) r |= GO_SEND_k r |= csn[k]=tsn[k] (by INV4(k) ) r |= csn[k]=csn[i] (by G6(k,i) r |= TX(csn[i]) r' |= TX(csn[i]) (start_message does not affect csn) r' |= last = csn[k] (effect start_message) r' |= last = csn[i] (start_message does not affect csn) Hence r' |= G7(i). Invariant G8(i) has been checked above Let's check G9(i). This is the difficult case. >From the proof of G4(i), we already know that r' |= last=csn[i]. Suppose r' |= clk[i] = k0 -1. We derive a contradiction. r |= clk[i] = k0 -1 (start-message[k] does not change clk) r |= GO_SEND_k (by precondition start_message[k]) r |= x_k = 0 /\ csn[k]=tsn[k] (by INV4 and INV5) r |= last =/= csn[k] (by G3(k) r |= clk[k] = g /\ forall l : csn[k] = csn[l] (by G6(k,.) ) r |= S0_i (by G9(i) ) r |= S0_k (by G9(k) ) Case 1. r |= last = -1 r |= c(k) = g r |= y <= g * max (by G1(k) ) r |= c(i) = k0 - 1 r |= y >= (k0 - 2)*min + x_i (by G2(i) ) >= (k0 - 2)*min (by INV1) Hence g * max >= (k0 - 2)*min But, as observed by Faranak, this contradicts constraint C1 since Lemma 4: g*max = M*k0*max - (M*k0 -g)*max <= <= M*k0*max - (M*k0 -g)*min < (by C1) < ((M+1)*k0 - g - 2)*min - (M*k0 - g)*min = = (k0 - 2)*min Case 2. r |= last >= 0 r |= c(k) = from(last,csn[k])*k0 r |= c(k) = D(csn[k])*k0 (by G7(k) ) r |= y <= D(csn[k] * k0 * max + x_k = (by G1(k) ) = D(csn[k] * k0 * max r |= c(i) = from(last,csn[i])*k0 + k0 - 1 - g = = D(csn[k])*k0 + k0 - 1 -g r |= y >= (D(csn[k])*k0 + k0 - 2 -g)*min + x_i (by G2(i) ) >= (D(csn[k])*k0 + k0 - 2 - g)*min Hence D(csn[k] * k0 * max >= (D(csn[k])*k0 + k0 - 2 - g)*min But since D(csn[k]) <= M, Lemma 1 gives D(csn[k] * k0 * max < (D(csn[k])*k0 + k0 - 2 - g)*min Contradiction! G10(i) has been checked above G11 is void G12(i) has been checked above CASE 3: a is a TICK[k] action ============================= Lemma 3: r'.c(k) = r.c(k) + 1 Proof: Case 1. r|= last = -1 Then r' |= last = -1 Hence r |= c(k) = clk[k] and r' |= c(k) = clk[k] By INV11, r |= S0_k and r' |= S0_k In the initial state csn[i]=0, for all nodes i By assumption, in the initial state csn[i]=tsn[i], for some i Hence TX(0). By G12(k), r |= csn[k]=0. Hence r |= TX(csn[k]) Together with G8(k), this implies clk[k] < k0 - 1 Hence r'.clk[k] = r.clk[k]+1 Hence r'.c(k) = r.c(k)+1, as required. Case 2. r |= last >=0 Case 2.1 r |= S1_k Then r |= c(k)=0 Also r' |= S0_k /\ clk[k]=g+1 By G9(k), r |= clk[k] < k0 -1 /\ last=csn[k] Hence r'.last = r.last and r'.csn[k]=r.csn[k] Hence r' |= c(k) = from(last,csn[k])*k0 + clk[k] - g = 1 Hence r'.c(k) = r.c(k)+1, as required. Case 2.2 r |= S0_k Then r' |= S0_k Case 2.2.1 r |= clk[k] < k0 - 1 Then r'.last = r.last r'.csn[k]= r.csn[k] r.clk[k] = r.clk[k]+1 Hence r'.c(k) = r'.from(last,csn[k])*k0 + r'.clk[k] - g = = r.from(last,csn[k])*k0 + r.clk[k] + 1 - g = = r.c(k) + 1 Case 2.2.2 r |= clk[k] = k0 - 1 r |= WAIT by INV6 and INV8 r'.last = r.last r'.clk[k] = 0 r'.csn[k] = (r.csn[k]+1) % C r'.from(last,csn[k]) = r.from(last,csn[k])+1 r'.c(k) = r'.from(last,csn[k]) * k0 + 0 - g = = r.from(last,csn[k])*k0 + k0 -1 - g + 1 = = r.c(k) + 1 This completes the proof of Lemma 3. QED Case G1(i) ========== >From Lemma 3, we may easily infer that G1(i) holds in r': If i =/= k then TICK[k] does not modify any variable in G1(i) and thus the invariant holds in r' because it holds in r. If i == k then r'.y = r.y <= (G1(i) holds in r) r.c(i) * max + r.x_i <= (INV1 holds in r) r.c(i) * max + max = (Lemma 3) r'.c(i) * max = (TICK[i] resets x_i) r'.c(i) * max + r'.x_i Case G2(i) ========== It also follows that G2(i) holds in r': Again, if i =/= k then TICK[k] does not modify any variable mentioned in G2(i) and the invariant holds in r' because it holds in r. If i == k then, using r |= G10(i), we can distinguish two cases: Case 1. r.c(i) = 0. Then r'.c(i) = 1 by Lemma 3. We infer r'.y >= (by INV9) 0 = (r'.c(i) -1) * min = (TICK[i] resets x_i) (r'.c(i) -1) * min + r'.x_i Case 2. r.c(i) > 0. Then also r'.c(i) > 0 by Lemma 3. We infer r'.y = r.y >= (r.c(i)-1)*min + r.x_i >= (by precondition TICk[i]) >= r.c(i) * min = (by Lemma 3) = (r'.c(i) - 1)* min = (TICK[i] resets x_i) = (r'.c(i) - 1)* min + r'.x_i Case G3(i) =========== We proceed to show that r' |= G3(i). If i =/= k then TICK[k] does not modify any variable mentioned in G3(i) and the invariant holds in r' because it holds in r. So wlog we may assume i=k. r'.last = r.last (TICK[i] does not modify last) r |= not GO_SEND_i (by INV4 and precondition TICK[i]) Case 1. r'.csn[i] = r.csn[i] Case 1.1 r |= csn[i]=tsn[i] /\ (clk[i] < g \/ GO_SEND_i) r |= last =/= csn[i] (since r |= G3(i) ) r' |= last =/= csn[i] (csn and last unchanged) r' |= G3(i) = Case 1.2. r |= csn[i]=/=tsn[i]. r' |= csn[i]=/=tsn[i] r' |= G3(i) Case 1.3. r |= csn[i]=tsn[i] /\ ( clk[i] >= g /\ (SENDING_i \/ WAIT_i) Given that r'.csn[i]=r.csn[i], we infer that r |=/= clk[i]=k0-1. This implies r' |= csn[i]=tsn[i] /\ ( clk[i] >= g /\ (SENDING_i \/ WAIT_i) Hence r' |= G3(i) Case 2. r'.csn[i] =/= r.csn[i] r |= WAIT_i /\ clk[i]=k0-1 r' |= WAIT_i /\ clk[i]=0 r'.csn[i]= (r.csn[i]+1)%C Case 2.1 r' |= csn[i] =/= tsn[i] Then r' | G3(i) Case 2.2 r' |= csn[i]=tsn[i] By G7 we can distinguish between 3 cases: Case 2.2.1 r |= last=-1 Then r' |= G3(i) Case 2.2.2 r |= TX(csn[i]) /\ last=csn[i] Then r' |= G3(i) Case 2.2.3 r |= last=PREV(csn[i]) Since there are at least 3 active slots, r' |= last =/= csn[i] Hence r' |= G3(i) Case G3a(i) =========== Next we establish r' |= G3a(i). If i =/= k then TICK[k] does not modify any variable mentioned in G3a(i) and the invariant holds in r' because it holds in r. So we may assume i=k. Assume r' |= csn[i]=tsn[i] /\ clk[i]=g Then r |= csn[i]=tsn[i] /\ clk[i]=g-1 Thus r |= WAIT_i (by INV6 and INV8) Thus r' |= GO_SEND_i This implies r' |= G3a(i). Case G4(i) ========== Now we will prove r' |= G4(i). If i =/= k then TICK[k] does not modify any variable mentioned in G4(i) and the invariant holds in r' because it holds in r. So we may assume i=k. Assume r' |= csn[i]=tsn[i] /\ clk[i]>g. We will prove that r' |= last=csn[i] Observe r |= csn[i]=tsn[i] Case 1. r |= clk[i]>g. Hence r |= last=csn[i] (by r |= G4(i)) Therefore r' |= last=csn[i] Case 2. r |= clk[i]=g. Hence r |= last=csn[i] (by r |= G3a(i) and INV4(i) ) Therefore r' |= last=csn[i] Case 3. r |= clk[i]= min r |= y >= (k0 - g - 2)* min + x_j by G2(j) >= (k0 - g -1) * min Thus (k0 - g - 1) * min <= (k0 - t - g) * max But this contradicts constraint C3! Case G6(i,j) ============ We continue to prove r' |= G6(i,j), the most difficult case in the proof. If i =/= k and j =/= k then TICK[k] does not modify any variable mentioned in G6(i,j) and the invariant holds in r' because it holds in r. Thus it suffices to consider the following two cases: Case 1. i=k Assume that r' |= GO_SEND_i. We must prove that r' |= csn[i] = csn[j] /\ clk[i]=g Since r --TICK[i]--> r' we know r |= WAIT_i /\ csn[i]=tsn[i] /\ clk[i]=g-1 /\ x_i >= min Case 1.1 r |= last = -1 r |= csn[i]=csn[j]=0 (by G12(i) and G12(j) ) r' |= csn[i]=csn[j] r |= S0_i (by INV11(i) ) r' |= clk[i]=g Case 1.2 r |= last >= 0 r |= last =/= csn[i] (by G3(i) ) r |= last = PREV(csn[i]) (by G7(i) ) r |= S0_i (by G9(i), use that s =/= PREV(s), for all s) r |= c(i) = D(csn[i])*k0 -1 (by def c(i) ) r |= y >= (D(csn[i])*k0 -1)*min (by G2(i) ) r |= y >= (D(csn[i])*k0 -1)*min >= > (k0 -1 )*min > (use C3) > (k0 -g -t)*max >= >= 2*max r |= S0_j (by INV10(j), INV1(j) and above inequality ) r |= c(j) = from(last, csn[j])*k0 + clk[j] - g r |= y <= (from(last, csn[j])*k0 +clk[j] -g + 1)*max (by G1(i) and INV1(j) ) Assume last=csn[j]. We derive a contradiction. r |= y <= (clk[j] - g + 1)*max <= (k0 - g)*max (by INV2(j) ) But also, by Lemma 2, r |= y>= (D(CSN[i])*k0 -1)*min >= (k0-1)*min > (k0-g)*max Contradiction. Since r |= last >= 0 and r|= last =/= csn[j], we infer using G7(j), r |= last=PREV(csn[j]) Let m_i = D(r.csn[i]) and m_j = D(r.csn[j]). Then, since TX(r.csn[i]) and PREV(r.csn[i])=PREV(r.csn[j]) it follows from the definition of PREV that m_j <= m_i (m_j*k0 + r.clk[j]-g+1)*max >= y >= (m_i*k0 -1)*min > (by Lemma 2) > (m_i * k0 - g ) * max Since max >0, this implies m_j*k0 +r.clk[j]-g+1 > m_i*k0 -g and thus m_j*k0 + r.clk[j] + 1 > m_i*k0 and thus (use k0 -1 >= r.clk[j] and k0 >0) m_j >= m_i Since both m_j <= m_i and m_j >= m_i, m_i=m_j. Since r |= PREV(csn[j]) = PREV(csn[i]), we conclude r |= csn[i]=csn[j] Hence r' |= csn[i]=csn[j] Using r |= S0_i, we also have r' |= clk[i]=g Case 2. j=k and i =/= k Assume r' |= GO_SEND_i We prove r' |= csn[i]=csn[j] /\ clk[i]=g Then r |= GO_SEND_i Then, by r |= G6(i,j), r |= csn[i]=csn[j] /\ clk[i]=g Action TICK[j] does not affect csn[i] and clk[i]. If also csn[j] is unchanged then r' |= csn[i]=csn[j] /\ clk[i]=g and we are done. Now assume that csn[j] is changed. Then r |= clk[j]=k0-1 r |= TX(csn[j]) r |= last=csn[j] (by G8(j) ) r |= last =/= csn[i] (by G3(i) ) This contradicts r |= csn[i]=csn[j] Case G7(i) ========== If i =/= k then TICK[k] does not modify any variable in G7(i) and thus the invariant holds in r' because it holds in r. So wlog we may assume i == k. r'.last = r.last If also r'.csn[i]=r.csn[i] then all variables in G7(i) remain unchanged and the invariant holds in r' because it holds in r. So wlog we may assume r'.csn[i] =/= r.csn[i]. r |= WAIT_i /\ clk[i] = k0 -1 r'.csn[i] = (r.csn[i]+1)%C If r.last = -1 then r'.last = -1 and r' |= G7(i). So wlog we may assume r.last =/= -1. Case 1. r |= TX(csn[i]) r |= last = csn[i] (by G8(i) ) We infer PREV(r'.csn[i]) = PREV((r.csn[i]+1)%C) = r.csn[i] = r.last = r'.last Hence r' |= G7(i) Case 2. r |=/= TX(csn[i]) r |= last=PREV(csn[i]) (by r |= G7(i) ) We infer PREV(r'.csn[i]) = PREV((r.csn[i]+1)%C) = PREV(r.csn[i]) = r.last = r'.last Hence r' |= G7(i) Case G8(i) ========== If i =/= k then TICK[k] does not modify any variable in G8(i) and thus the invariant holds in r' because it holds in r. So wlog we may assume i == k. Assume r' |= TX(csn[i]) /\ clk[i]=k0-1. We must prove r' |= last=csn[i]. r'csn[i]=r.csn[i] r'.last = r.last r |= TX(csn[i]) /\ clk[i]=k0-2 /\ x_i >=min Assume r |= last = -1. We derive a contradiction. r |= forall k : csn[k]=0 (by G12) Let j such that r|= csn[j]=tsn[j] (we assumed some node transmits in initial slot) r |= c(i) = clk[i] = k0 -2 r |= y >= (k0 - 2)*min > (by Lemma 4) > g*max r |= y <= c(j)*max + x_j = clk[j]*max + x_j Case 1. r |= x_j=0. Then r |= clk[j]*max > g*max and thus clk[j]>g Hence by G4, r|= last=csn[j]. Contradiction Case 2. r |= x_j > 0 Then r |= (clk[j]+1)*max > g*max and thus r |= clk[j] >= g If r |= clk[j]>g then by G4 r |= last=csn[j] and we have a contrdiction. If r |= clk[j]=g then r |= GO_SEND_j \/ SENDING_j In fact, using INV4(j) we infer r |= SENDING_j Hence, by r |= G5(j,i) r |= csn[j]=last, again a contradiction. So we may conclude that r |=/= last = -1. Assume r |= last = PREV(csn[i]). Again we derive a contradiction. r |= last =/= csn[i] (by def PREV) r |= S0_i (by G9(i) ) r |= c(i) = D(csn[i])*k0 + k0 - 2 - g r |= y >= (D(csn[i])*k0 + k0 - 2 - g)*min > (by Lemma 1) > D(csn[i]) * k0 * max Let j be the unique node such that tsn[j]=r.csn[i] r |= y <= (c(j)+1)*max r |= c(j) >= D(csn[i])*k0 r |= S0_j r |= c(j)=from(last,csn[j])*k0 + clk[j] -g r |= from(last,csn[j]) >= D(csn[i]) r |= last=PREV(csn[j]) (by G8) r |= csn[j]=csn[i] (by def PREV) r |= clk[j] >= g If in fact r |= clk[j] > g then by INV4(j) r |= last=csn[j] (= csn[i]) and we have a contradiction. So we may assume r |= clk[j]=g Case 1. r |= x_j > 0 Then by G3a and INV4 r |= SENDING_j Thus by G5(j,i) csn[i]=last Contradiction Case 2. r |= x_j=0 Then r |= y <= c(j)*max and thus r |= c(j)*max > D(csn[i]) * k0 * max This implies r |= c(j) > D(csn[i]) * k0 and thus r |= clk[j] > g Therefor, by r |= G4(j), r |= last=csn[j] (= csn[i]) Contradiction By r |= G7(i) we conclude that r |= last=csn[i]. Hence r' |=last=csn[i], as required. Case G9(i) ========== If i =/= k then TICK[k] does not modify any variable in G9(i) and thus the invariant holds in r' because it holds in r. So wlog we may assume i == k. But since r --TICK[i]--> r', it follows that r' |= S0_i. Thus r' |= G9(i). Case G10(i) =========== Immediate from Lemma 3. Case G12(i) =========== If i =/= k then TICK[k] does not modify any variable in G12(i) and thus the invariant holds in r' because it holds in r. So wlog we may assume i == k. Assume r'.last = -1. We will prove r' |= csn[i]=0. r'.last = r.last r.last = -1 r |= csn[i] = 0 (by G12(i) ) If also r'.csn[i]=r.csn[i] then we are done. So wlog we may assume r'.csn[i] =/= r.csn[i]. r |= clk[i] = k0 -1 r |= TX(csn[i]) (by assumption on tsn) r |= last = csn[i] (by G8(i) ) r |= last =/= -1 (by INV3(i) ) Contradiction.