Case Analysis in CCRW, 2

Case Analysis in Circular Coinductive Rewriting, 2

Here we apply BOBJ's circular coinductive rewriting algorithm, with its new feature for case analysis, to a real time asynchronous data transmission protocol. The spec and the proof are both due to Profs. Futatsugi and Ogata of JAIST (see Rewriting can verify distributed real-time systems - how to verify in CafeOBJ, in Proc. Int. Workshop on Rewriting in Proof and Computation, pp. 60-79, 2001). However the presentation of this proof is much simplified by using BOBJ's case analysis features, including named case declarations (so that they are first class citizens, that can be reused), "multiplying" cases to form compound cases (the cartesian product of the cases of the components), and excluding cases from a product (e.g., because they cannot occur). These features were developed jointly by Joseph Goguen and Kai Lin, and were implemented by Kai Lin.


1. BOBJ Source Code

dth BASIC-INT is sorts Zero NzNat Nat NgInt NpInt Int . subsort Zero NzNat < Nat . subsort NgInt Zero < NpInt . subsort NgInt Zero NpInt NzNat Nat < Int . op 0 : -> Zero . op s_ : Nat -> NzNat . op p_ : NpInt -> NgInt . op s_ : Int -> Int . op p_ : Int -> Int . var I : Int . eq s p I = I . eq p s I = I . end dth INT* is pr BASIC-INT . op _+_ : Int Int -> Int [assoc comm]. vars I J : Int . var N : NzNat . eq I + 0 = I . eq I + s J = s(I + J) . eq I + p J = p(I + J) . op -_ : Int -> Int . eq - 0 = 0 . eq - (s I) = p (- I) . eq - (p I) = s (- I) . op _*_ : Int Int -> Int . eq 0 * J = 0 . eq (s I) * J = J + (I * J) . eq (p I) * J = (- J) + (I * J) . ops inc dec : Int -> Int . eq inc(I) = s I . eq dec(I) = p I . op _<_ : Int Int -> Bool . eq I < I + N = true . end dth LIST [X :: TRIV]is sort List . op nil : -> List . op _$_ : Elt List -> List . op car_ : List -> Elt . op cdr_ : List -> List . var E : Elt . var L : List . eq car (E $ L) = E . eq cdr (E $ L) = L . end dth ILIST is pr LIST[INT*]. op 0 upto _ : Int -> List . var N : NgInt . var M : Nat . var I : Int . var L : List . eq 0 upto N = nil . eq 0 upto 0 = nil . eq 0 upto (s M) = (M $ (0 upto M)) . eq cdr (0 upto I) = 0 upto (p I) . eq (s I) $ (0 upto I) = 0 upto (s I) . eq I $ (0 upto p I) = 0 upto I . op put : List Int -> List . eq put(L, I) = I $ L . end th REAL+ is sorts Real+ Timeval Timeval0 . subsort Real+ Timeval < Timeval0 . op 0 : -> Real+ . op oo : -> Timeval . op _+_ : Timeval0 Timeval0 -> Timeval0 [comm]. op _+_ : Real+ Real+ -> Real+ [comm]. op _+_ : Timeval Timeval -> Timeval [comm]. op _<=_ : Timeval0 Timeval0 -> Bool . op _<_ : Timeval0 Timeval0 -> Bool . vars T1 T2 T3 : Timeval0 . eq T1 + T2 <= T1 + T3 = T2 <= T3 . eq T1 + T2 < T1 + T3 = T2 < T3 . end ***> distributed real-time asynchoronous data transmission protocol bth ASEND is sort Sys . protecting INT* + ILIST + REAL+ . op init : -> Sys . op empty : Sys -> Bool . ops content data : Sys -> Nat . op list : Sys -> List . ops now l : Sys -> Real+ . op u : Sys -> Timeval . ops send rec : Sys -> Sys . op tick : Sys Real+ -> Sys . op d1 : -> Real+ . *** minimum delay for send op d2 : -> Real+ . *** maximum delay for rec eq d2 < d1 = true . var T : Timeval0 . var S : Sys . var D : Real+ . eq T < T + d1 = true . eq empty(init) = true . eq data(init) = 0 . eq list(init) = nil . eq now(init) = 0 . eq l(init) = d1 . eq u(init) = oo . ceq empty(send(S)) = false if l(S) <= now(S) . ceq empty(send(S)) = empty(S) if now(S) < l(S) . ceq content(send(S)) = data(S) if l(S) <= now(S) . ceq content(send(S)) = content(S) if now(S) < l(S) . ceq data(send(S)) = inc(data(S)) if l(S) <= now(S) . ceq data(send(S)) = data(S) if now(S) < l(S) . eq list(send(S)) = list(S) . eq now(send(S)) = now(S) . ceq l(send(S)) = now(S) + d1 if l(S) <= now(S) . ceq l(send(S)) = l(S) if now(S) < l(S) . ceq u(send(S)) = now(S) + d2 if l(S) <= now(S) . ceq u(send(S)) = u(S) if now(S) < l(S) . ceq empty(rec(S)) = true if empty(S) == false . ceq empty(rec(S)) = empty(S) if empty(S) == true . eq content(rec(S)) = content(S) . eq data(rec(S)) = data(S) . ceq list(rec(S)) = put(list(S),content(S)) if empty(S) == false . ceq list(rec(S)) = list(S) if empty(S) == true . eq now(rec(S)) = now(S) . eq l(rec(S)) = l(S) . ceq u(rec(S)) = oo if empty(S) == false . ceq u(rec(S)) = u(S) if empty(S) == true . eq empty(tick(S,D)) = empty(S) . eq content(tick(S,D)) = content(S) . eq data(tick(S,D)) = data(S) . eq list(tick(S,D)) = list(S) . ceq now(tick(S,D)) = now(S) + D if now(S) + D <= u(S) . ceq now(tick(S,D)) = now(S) if u(S) < now(S) + D . eq l(tick(S,D)) = l(S) . eq u(tick(S,D)) = u(S) . end dth INV is protecting ASEND . *** inv1 is the property we want to prove about the spec ASEND op inv1 : Sys -> Bool . var S : Sys . eq inv1(S) = (empty(S) implies (list(S) == 0 upto dec(data(S)))) and (not(empty(S)) implies (list(S) == 0 upto dec(dec(data(S))))) . op inv2 : Sys -> Bool . eq inv2(S) = empty(S) or (now(S) < l(S)) . op inv3 : Sys -> Bool . eq inv3(S) = (u(S) < l(S)) or empty(S) . op inv4 : Sys -> Bool . eq inv4(S) = (content(S) == dec(data(S))) or empty(S) . end ***> induction base: ***> inv1(init), inv2(init), inv3(init), inv4(init) hold open INV . red inv1(init) . red inv2(init) . red inv3(init) . red inv4(init) . close dth BASE is protecting INV . op s : -> Sys . var D : Real+ . end cases C1 for BASE is context s . case eq empty(s) = true . case eq empty(s) = false . end cases C2 for BASE is context s . case eq now(s) < l(s) = true . case eq l(s) <= now(s) = true . end cases C3 for BASE is var D : Real+ . context tick(s, D) . case eq now(s) + D <= u(s) = true . case eq u(s) < now(s) + D = true . end ***> ==== proof score for inv3 and inv4 ======= *** module for induction BASE for inv3 and inv4 dth BASE3and4 is protecting BASE . *** inv3 ceq u(s) < l(s) = true if not(empty(s)) . *** inv4 ceq content(s) = dec(data(s)) if not(empty(s)) . end open BASE3and4 . use C1 * C2 . cred inv3(send(s)) == true . cred inv4(send(s)) == true . cred inv3(rec(s)) == true . cred inv4(rec(s)) == true . op d : -> Real+ . cred inv3(tick(s,d)) == true . cred inv4(tick(s,d)) == true . close ***> ==== proof score for inv2 ======= dth BASE2 is protecting BASE . *** lemmata inv3 and inv4 are already proved var S : Sys . var D : Timeval0 . ceq (u(S) < l(S)) = true if not(empty(S)) . ceq content(S) = dec(data(S)) if not(empty(S)) . *** necessary proposition: validity is trivial ceq ((now(S) + D) < l(S)) = true if ((now(S) + D) <= u(S)) and (u(S) < l(S)) . *** inv2 ceq (now(s) < l(s)) = true if not(empty(s)) . end open BASE2 . use C1 * C2 . cred inv2(send(s)) == true . cred inv2(rec(s)) == true . op d : -> Real+ . cred with C3 * C1 * C2 inv2(tick(s,d)) == true . close ***> ==== proof score for inv1 ======= dth BASE1 is protecting BASE . var S : Sys . ceq (now(S) < l(S)) = true if not(empty(S)) . ceq (u(S) < l(S)) = true if not(empty(S)) . ceq content(S) = dec(data(S)) if not(empty(S)) . *** inv1: the property to be proved ceq list(s) = (0 upto dec(data(s))) if empty(s) . ceq list(s) = (0 upto dec(dec(data(s)))) if not(empty(s)) . end open BASE1 . cred with C1 * C2 exclude (2,2) inv1(send(s)) == true . cred with C1 inv1(rec(s)) == true . op d : -> Real+ . cred with C1 inv1(tick(s, d)) == true . close

2. BOBJ Output with Full Trace Off

We first give the output with full trace off, which is much more compact, though less informative, than the output with full trace on, as shown in the next section below. awk% bobj \|||||||||||||||||/ --- Welcome to BOBJ --- /|||||||||||||||||\ BOBJ version 0.9.146 built: Mon Jan 7 18:30:55 PST 2002 University of California, San Diego Tue Jan 08 13:14:43 PST 2002 BOBJ> in realcase ========================================== dth BASIC-INT ========================================== dth INT* ========================================== dth LIST ========================================== dth ILIST ========================================== th REAL+ ========================================== ***> distributed real-time asynchoronous data transmission protocol ========================================== bth ASEND ========================================== dth INV ========================================== ***> induction base: ========================================== ***> inv1(init), inv2(init), inv3(init), inv4(init) hold ========================================== open INV ========================================== reduce in INV : inv1(init) result Bool: true rewrite time: 144ms parse time: 1ms ========================================== reduce in INV : inv2(init) result Bool: true rewrite time: 2ms parse time: 2ms ========================================== reduce in INV : inv3(init) result Bool: true rewrite time: 22ms parse time: 1ms ========================================== reduce in INV : inv4(init) result Bool: true rewrite time: 3ms parse time: 1ms ========================================== close ========================================== dth BASE ========================================== cases C1 ========================================== cases C2 ========================================== cases C3 ========================================== ***> ==== proof score for inv3 and inv4 ======= ========================================== dth BASE3and4 ========================================== open BASE3and4 ========================================== use C1 * C2 ========================================== c-reduce in BASE3and4 : inv3(send(s)) == true result: true c-rewrite time: 85ms parse time: 11ms ========================================== c-reduce in BASE3and4 : inv4(send(s)) == true result: true c-rewrite time: 57ms parse time: 3ms ========================================== c-reduce in BASE3and4 : inv3(rec(s)) == true result: true c-rewrite time: 46ms parse time: 4ms ========================================== c-reduce in BASE3and4 : inv4(rec(s)) == true result: true c-rewrite time: 42ms parse time: 3ms ========================================== op d : -> Real+ ========================================== c-reduce in BASE3and4 : inv3(tick(s, d)) == true result: true c-rewrite time: 44ms parse time: 4ms ========================================== c-reduce in BASE3and4 : inv4(tick(s, d)) == true result: true c-rewrite time: 39ms parse time: 4ms ========================================== close ========================================== ***> ==== proof score for inv2 ======= ========================================== dth BASE2 ========================================== open BASE2 ========================================== use C1 * C2 ========================================== c-reduce in BASE2 : inv2(send(s)) == true result: true c-rewrite time: 46ms parse time: 3ms ========================================== c-reduce in BASE2 : inv2(rec(s)) == true result: true c-rewrite time: 32ms parse time: 3ms ========================================== op d : -> Real+ ========================================== c-reduce in BASE2 : inv2(tick(s, d)) == true use: C3 * C1 * C2 result: true c-rewrite time: 87ms parse time: 4ms ========================================== close ========================================== ***> ==== proof score for inv1 ======= ========================================== dth BASE1 ========================================== open BASE1 ========================================== c-reduce in BASE1 : inv1(send(s)) == true use: C1 * C2 exclude (2,2) result: true c-rewrite time: 99ms parse time: 3ms ========================================== c-reduce in BASE1 : inv1(rec(s)) == true use: C1 result: true c-rewrite time: 81ms parse time: 4ms ========================================== op d : -> Real+ ========================================== c-reduce in BASE1 : inv1(tick(s, d)) == true use: C1 result: true c-rewrite time: 69ms parse time: 4ms ========================================== close BOBJ> q Bye.

3. BOBJ Output with Full Trace On

We next give the output with full trace on, which shows many more details about the computations that are performed. awk% bobj \|||||||||||||||||/ --- Welcome to BOBJ --- /|||||||||||||||||\ BOBJ version 0.9.146 built: Mon Jan 7 18:30:55 PST 2002 University of California, San Diego Tue Jan 08 13:14:56 PST 2002 BOBJ> set full trace on . BOBJ> in realcase ========================================== dth BASIC-INT ========================================== dth INT* ========================================== dth LIST ========================================== dth ILIST ========================================== th REAL+ ========================================== ***> distributed real-time asynchoronous data transmission protocol ========================================== bth ASEND ========================================== dth INV ========================================== ***> induction base: ========================================== ***> inv1(init), inv2(init), inv3(init), inv4(init) hold ========================================== open INV ========================================== reduce in INV : inv1(init) result Bool: true rewrite time: 158ms parse time: 1ms ========================================== reduce in INV : inv2(init) result Bool: true rewrite time: 2ms parse time: 2ms ========================================== reduce in INV : inv3(init) result Bool: true rewrite time: 22ms parse time: 1ms ========================================== reduce in INV : inv4(init) result Bool: true rewrite time: 4ms parse time: 2ms ========================================== close ========================================== dth BASE ========================================== cases C1 ========================================== cases C2 ========================================== cases C3 ========================================== ***> ==== proof score for inv3 and inv4 ======= ========================================== dth BASE3and4 ========================================== open BASE3and4 ========================================== use C1 * C2 ========================================== c-reduce in BASE3and4 : inv3(send(s)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv3(send(s)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv3(send(s)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv3(send(s)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv3(send(s)) == true nf: true ------------------------------- result: true c-rewrite time: 101ms parse time: 11ms ========================================== c-reduce in BASE3and4 : inv4(send(s)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv4(send(s)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv4(send(s)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv4(send(s)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv4(send(s)) == true nf: true ------------------------------- result: true c-rewrite time: 63ms parse time: 3ms ========================================== c-reduce in BASE3and4 : inv3(rec(s)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv3(rec(s)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv3(rec(s)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv3(rec(s)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv3(rec(s)) == true nf: true ------------------------------- result: true c-rewrite time: 59ms parse time: 3ms ========================================== c-reduce in BASE3and4 : inv4(rec(s)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv4(rec(s)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv4(rec(s)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv4(rec(s)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv4(rec(s)) == true nf: true ------------------------------- result: true c-rewrite time: 54ms parse time: 3ms ========================================== op d : -> Real+ ========================================== c-reduce in BASE3and4 : inv3(tick(s, d)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv3(tick(s, d)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv3(tick(s, d)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv3(tick(s, d)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv3(tick(s, d)) == true nf: true ------------------------------- result: true c-rewrite time: 58ms parse time: 3ms ========================================== c-reduce in BASE3and4 : inv4(tick(s, d)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv4(tick(s, d)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv4(tick(s, d)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv4(tick(s, d)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv4(tick(s, d)) == true nf: true ------------------------------- result: true c-rewrite time: 53ms parse time: 4ms ========================================== close ========================================== ***> ==== proof score for inv2 ======= ========================================== dth BASE2 ========================================== open BASE2 ========================================== use C1 * C2 ========================================== c-reduce in BASE2 : inv2(send(s)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv2(send(s)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv2(send(s)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv2(send(s)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv2(send(s)) == true nf: true ------------------------------- result: true c-rewrite time: 64ms parse time: 3ms ========================================== c-reduce in BASE2 : inv2(rec(s)) == true ------------------------------------------- case analyse by C1 * C2 ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv2(rec(s)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv2(rec(s)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv2(rec(s)) == true nf: true ------------------------------- case (2,2) : assume: empty(s) = false l(s) <= now(s) = true reduce: inv2(rec(s)) == true nf: true ------------------------------- result: true c-rewrite time: 45ms parse time: 3ms ========================================== op d : -> Real+ ========================================== c-reduce in BASE2 : inv2(tick(s, d)) == true use: C3 * C1 * C2 ------------------------------------------- case analyse by C3 * C1 * C2 ------------------------------------------- case (1,1,1) : assume: (now(s) + d) <= u(s) = true empty(s) = true now(s) < l(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- case (1,1,2) : assume: (now(s) + d) <= u(s) = true empty(s) = true l(s) <= now(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- case (1,2,1) : assume: (now(s) + d) <= u(s) = true empty(s) = false now(s) < l(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- case (1,2,2) : assume: (now(s) + d) <= u(s) = true empty(s) = false l(s) <= now(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- case (2,1,1) : assume: u(s) < (now(s) + d) = true empty(s) = true now(s) < l(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- case (2,1,2) : assume: u(s) < (now(s) + d) = true empty(s) = true l(s) <= now(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- case (2,2,1) : assume: u(s) < (now(s) + d) = true empty(s) = false now(s) < l(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- case (2,2,2) : assume: u(s) < (now(s) + d) = true empty(s) = false l(s) <= now(s) = true reduce: inv2(tick(s, d)) == true nf: true ------------------------------- result: true c-rewrite time: 104ms parse time: 4ms ========================================== close ========================================== ***> ==== proof score for inv1 ======= ========================================== dth BASE1 ========================================== open BASE1 ========================================== c-reduce in BASE1 : inv1(send(s)) == true use: C1 * C2 exclude (2,2) ------------------------------------------- case analyse by C1 * C2 exclude (2,2) ------------------------------------------- case (1,1) : assume: empty(s) = true now(s) < l(s) = true reduce: inv1(send(s)) == true nf: true ------------------------------- case (1,2) : assume: empty(s) = true l(s) <= now(s) = true reduce: inv1(send(s)) == true nf: true ------------------------------- case (2,1) : assume: empty(s) = false now(s) < l(s) = true reduce: inv1(send(s)) == true nf: true ------------------------------- result: true c-rewrite time: 117ms parse time: 3ms ========================================== c-reduce in BASE1 : inv1(rec(s)) == true use: C1 ------------------------------------------- case analyse by C1 ------------------------------------------- case 1 : assume: empty(s) = true reduce: inv1(rec(s)) == true nf: true ------------------------------- case 2 : assume: empty(s) = false reduce: inv1(rec(s)) == true nf: true ------------------------------- result: true c-rewrite time: 74ms parse time: 3ms ========================================== op d : -> Real+ ========================================== c-reduce in BASE1 : inv1(tick(s, d)) == true use: C1 ------------------------------------------- case analyse by C1 ------------------------------------------- case 1 : assume: empty(s) = true reduce: inv1(tick(s, d)) == true nf: true ------------------------------- case 2 : assume: empty(s) = false reduce: inv1(tick(s, d)) == true nf: true ------------------------------- result: true c-rewrite time: 82ms parse time: 4ms ========================================== close BOBJ> q Bye. awk%


To the BOBJ Examples homepage
To the Tatami project homepage
Maintained by Joseph Goguen
Last modified: Fri Jan 10 12:59:03 PST 2003