Theory OG_Examples
section ‹Examples›
theory OG_Examples imports OG_Syntax begin
subsection ‹Mutual Exclusion›
subsubsection ‹Peterson's Algorithm I›
text ‹Eike Best. "Semantics of Sequential and Parallel Programs", page 217.›
record Petersons_mutex_1 =
 pr1 :: nat
 pr2 :: nat
 in1 :: bool
 in2 :: bool
 hold :: nat
lemma Petersons_mutex_1:
  "∥- ⦃´pr1=0 ∧ ¬´in1 ∧ ´pr2=0 ∧ ¬´in2 ⦄
  COBEGIN ⦃´pr1=0 ∧ ¬´in1⦄
  WHILE True INV ⦃´pr1=0 ∧ ¬´in1⦄
  DO
  ⦃´pr1=0 ∧ ¬´in1⦄ ⟨ ´in1:=True,,´pr1:=1 ⟩;;
  ⦃´pr1=1 ∧ ´in1⦄  ⟨ ´hold:=1,,´pr1:=2 ⟩;;
  ⦃´pr1=2 ∧ ´in1 ∧ (´hold=1 ∨ ´hold=2 ∧ ´pr2=2)⦄
  AWAIT (¬´in2 ∨ ¬(´hold=1)) THEN ´pr1:=3 END;;
  ⦃´pr1=3 ∧ ´in1 ∧ (´hold=1 ∨ ´hold=2 ∧ ´pr2=2)⦄
   ⟨´in1:=False,,´pr1:=0⟩
  OD ⦃´pr1=0 ∧ ¬´in1⦄
  ∥
  ⦃´pr2=0 ∧ ¬´in2⦄
  WHILE True INV ⦃´pr2=0 ∧ ¬´in2⦄
  DO
  ⦃´pr2=0 ∧ ¬´in2⦄ ⟨ ´in2:=True,,´pr2:=1 ⟩;;
  ⦃´pr2=1 ∧ ´in2⦄ ⟨  ´hold:=2,,´pr2:=2 ⟩;;
  ⦃´pr2=2 ∧ ´in2 ∧ (´hold=2 ∨ (´hold=1 ∧ ´pr1=2))⦄
  AWAIT (¬´in1 ∨ ¬(´hold=2)) THEN ´pr2:=3  END;;
  ⦃´pr2=3 ∧ ´in2 ∧ (´hold=2 ∨ (´hold=1 ∧ ´pr1=2))⦄
    ⟨´in2:=False,,´pr2:=0⟩
  OD ⦃´pr2=0 ∧ ¬´in2⦄
  COEND
  ⦃´pr1=0 ∧ ¬´in1 ∧ ´pr2=0 ∧ ¬´in2⦄"
apply oghoare
apply auto
done
subsubsection ‹Peterson's Algorithm II: A Busy Wait Solution›
text ‹Apt and Olderog. "Verification of sequential and concurrent Programs", page 282.›
record Busy_wait_mutex =
 flag1 :: bool
 flag2 :: bool
 turn  :: nat
 after1 :: bool
 after2 :: bool
lemma Busy_wait_mutex:
 "∥-  ⦃True⦄
  ´flag1:=False,, ´flag2:=False,,
  COBEGIN ⦃¬´flag1⦄
        WHILE True
        INV ⦃¬´flag1⦄
        DO ⦃¬´flag1⦄ ⟨ ´flag1:=True,,´after1:=False ⟩;;
           ⦃´flag1 ∧ ¬´after1⦄ ⟨ ´turn:=1,,´after1:=True ⟩;;
           ⦃´flag1 ∧ ´after1 ∧ (´turn=1 ∨ ´turn=2)⦄
            WHILE ¬(´flag2 ⟶ ´turn=2)
            INV ⦃´flag1 ∧ ´after1 ∧ (´turn=1 ∨ ´turn=2)⦄
            DO ⦃´flag1 ∧ ´after1 ∧ (´turn=1 ∨ ´turn=2)⦄ SKIP OD;;
           ⦃´flag1 ∧ ´after1 ∧ (´flag2 ∧ ´after2 ⟶ ´turn=2)⦄
            ´flag1:=False
        OD
       ⦃False⦄
  ∥
     ⦃¬´flag2⦄
        WHILE True
        INV ⦃¬´flag2⦄
        DO ⦃¬´flag2⦄ ⟨ ´flag2:=True,,´after2:=False ⟩;;
           ⦃´flag2 ∧ ¬´after2⦄ ⟨ ´turn:=2,,´after2:=True ⟩;;
           ⦃´flag2 ∧ ´after2 ∧ (´turn=1 ∨ ´turn=2)⦄
            WHILE ¬(´flag1 ⟶ ´turn=1)
            INV ⦃´flag2 ∧ ´after2 ∧ (´turn=1 ∨ ´turn=2)⦄
            DO ⦃´flag2 ∧ ´after2 ∧ (´turn=1 ∨ ´turn=2)⦄ SKIP OD;;
           ⦃´flag2 ∧ ´after2 ∧ (´flag1 ∧ ´after1 ⟶ ´turn=1)⦄
            ´flag2:=False
        OD
       ⦃False⦄
  COEND
  ⦃False⦄"
apply oghoare
apply auto
done
subsubsection ‹Peterson's Algorithm III: A Solution using Semaphores›
record  Semaphores_mutex =
 out :: bool
 who :: nat
lemma Semaphores_mutex:
 "∥- ⦃i≠j⦄
  ´out:=True ,,
  COBEGIN ⦃i≠j⦄
       WHILE True INV ⦃i≠j⦄
       DO ⦃i≠j⦄ AWAIT ´out THEN  ´out:=False,, ´who:=i END;;
          ⦃¬´out ∧ ´who=i ∧ i≠j⦄ ´out:=True OD
       ⦃False⦄
  ∥
       ⦃i≠j⦄
       WHILE True INV ⦃i≠j⦄
       DO ⦃i≠j⦄ AWAIT ´out THEN  ´out:=False,,´who:=j END;;
          ⦃¬´out ∧ ´who=j ∧ i≠j⦄ ´out:=True OD
       ⦃False⦄
  COEND
  ⦃False⦄"
apply oghoare
apply auto
done
subsubsection ‹Peterson's Algorithm III: Parameterized version:›
lemma Semaphores_parameterized_mutex:
 "0<n ⟹ ∥- ⦃True⦄
  ´out:=True ,,
 COBEGIN
  SCHEME [0≤ i< n]
    ⦃True⦄
     WHILE True INV ⦃True⦄
      DO ⦃True⦄ AWAIT ´out THEN  ´out:=False,, ´who:=i END;;
         ⦃¬´out ∧ ´who=i⦄ ´out:=True OD
    ⦃False⦄
 COEND
  ⦃False⦄"
apply oghoare
apply auto
done
subsubsection‹The Ticket Algorithm›
record Ticket_mutex =
 num :: nat
 nextv :: nat
 turn :: "nat list"
 index :: nat
lemma Ticket_mutex:
 "⟦ 0<n; I=«n=length ´turn ∧ 0<´nextv ∧ (∀k l. k<n ∧ l<n ∧ k≠l
    ⟶ ´turn!k < ´num ∧ (´turn!k =0 ∨ ´turn!k≠´turn!l))» ⟧
   ⟹ ∥- ⦃n=length ´turn⦄
   ´index:= 0,,
   WHILE ´index < n INV ⦃n=length ´turn ∧ (∀i<´index. ´turn!i=0)⦄
    DO ´turn:= ´turn[´index:=0],, ´index:=´index +1 OD,,
  ´num:=1 ,, ´nextv:=1 ,,
 COBEGIN
  SCHEME [0≤ i< n]
    ⦃´I⦄
     WHILE True INV ⦃´I⦄
      DO ⦃´I⦄ ⟨ ´turn :=´turn[i:=´num],, ´num:=´num+1 ⟩;;
         ⦃´I⦄ WAIT ´turn!i=´nextv END;;
         ⦃´I ∧ ´turn!i=´nextv⦄ ´nextv:=´nextv+1
      OD
    ⦃False⦄
 COEND
  ⦃False⦄"
apply oghoare
apply simp_all
apply(tactic ‹ALLGOALS (clarify_tac \<^context>)›)
apply simp_all
apply(tactic ‹ALLGOALS (clarify_tac \<^context>)›)
apply(erule less_SucE)
 apply simp
apply simp
apply(case_tac "i=k")
 apply force
apply simp
apply(case_tac "i=l")
 apply force
apply force
prefer 8
apply force
apply force
prefer 6
apply(erule_tac x=j in allE)
apply fastforce
prefer 5
apply(case_tac [!] "j=k")
apply simp_all
apply(erule_tac x=k in allE)
apply force
apply(case_tac "j=l")
 apply simp
 apply(erule_tac x=k in allE)
 apply(erule_tac x=k in allE)
 apply(erule_tac x=l in allE)
 apply force
apply(erule_tac x=k in allE)
apply(erule_tac x=k in allE)
apply(erule_tac x=l in allE)
apply force
apply force
apply(case_tac "j=l")
 apply simp
apply(erule_tac x=k in allE)
apply(erule_tac x=l in allE)
apply force
apply force
apply force
apply(erule_tac x=k in allE)
apply(erule_tac x=l in allE)
apply(case_tac "j=l")
 apply force
apply force
apply force
apply(erule_tac x=k in allE)
apply(erule_tac x=l in allE)
apply(case_tac "j=l")
 apply force
apply force
apply force
apply(erule_tac x=k in allE)
apply(erule_tac x=l in allE)
apply(case_tac "j=l")
 apply force
apply force
done
subsection‹Parallel Zero Search›
text ‹Synchronized Zero Search. Zero-6›
text ‹Apt and Olderog. "Verification of sequential and concurrent Programs" page 294:›
record Zero_search =
   turn :: nat
   found :: bool
   x :: nat
   y :: nat
lemma Zero_search:
  "⟦I1= « a≤´x ∧ (´found ⟶ (a<´x ∧ f(´x)=0) ∨ (´y≤a ∧ f(´y)=0))
      ∧ (¬´found ∧ a<´ x ⟶ f(´x)≠0) » ;
    I2= «´y≤a+1 ∧ (´found ⟶ (a<´x ∧ f(´x)=0) ∨ (´y≤a ∧ f(´y)=0))
      ∧ (¬´found ∧ ´y≤a ⟶ f(´y)≠0) » ⟧ ⟹
  ∥- ⦃∃ u. f(u)=0⦄
  ´turn:=1,, ´found:= False,,
  ´x:=a,, ´y:=a+1 ,,
  COBEGIN ⦃´I1⦄
       WHILE ¬´found
       INV ⦃´I1⦄
       DO ⦃a≤´x ∧ (´found ⟶ ´y≤a ∧ f(´y)=0) ∧ (a<´x ⟶ f(´x)≠0)⦄
          WAIT ´turn=1 END;;
          ⦃a≤´x ∧ (´found ⟶ ´y≤a ∧ f(´y)=0) ∧ (a<´x ⟶ f(´x)≠0)⦄
          ´turn:=2;;
          ⦃a≤´x ∧ (´found ⟶ ´y≤a ∧ f(´y)=0) ∧ (a<´x ⟶ f(´x)≠0)⦄
          ⟨ ´x:=´x+1,,
            IF f(´x)=0 THEN ´found:=True ELSE SKIP FI⟩
       OD;;
       ⦃´I1  ∧ ´found⦄
       ´turn:=2
       ⦃´I1 ∧ ´found⦄
  ∥
      ⦃´I2⦄
       WHILE ¬´found
       INV ⦃´I2⦄
       DO ⦃´y≤a+1 ∧ (´found ⟶ a<´x ∧ f(´x)=0) ∧ (´y≤a ⟶ f(´y)≠0)⦄
          WAIT ´turn=2 END;;
          ⦃´y≤a+1 ∧ (´found ⟶ a<´x ∧ f(´x)=0) ∧ (´y≤a ⟶ f(´y)≠0)⦄
          ´turn:=1;;
          ⦃´y≤a+1 ∧ (´found ⟶ a<´x ∧ f(´x)=0) ∧ (´y≤a ⟶ f(´y)≠0)⦄
          ⟨ ´y:=(´y - 1),,
            IF f(´y)=0 THEN ´found:=True ELSE SKIP FI⟩
       OD;;
       ⦃´I2 ∧ ´found⦄
       ´turn:=1
       ⦃´I2 ∧ ´found⦄
  COEND
  ⦃f(´x)=0 ∨ f(´y)=0⦄"
apply oghoare
apply auto
done
text ‹Easier Version: without AWAIT.  Apt and Olderog. page 256:›
lemma Zero_Search_2:
"⟦I1=« a≤´x ∧ (´found ⟶ (a<´x ∧ f(´x)=0) ∨ (´y≤a ∧ f(´y)=0))
    ∧ (¬´found ∧ a<´x ⟶ f(´x)≠0)»;
 I2= «´y≤a+1 ∧ (´found ⟶ (a<´x ∧ f(´x)=0) ∨ (´y≤a ∧ f(´y)=0))
    ∧ (¬´found ∧ ´y≤a ⟶ f(´y)≠0)»⟧ ⟹
  ∥- ⦃∃u. f(u)=0⦄
  ´found:= False,,
  ´x:=a,, ´y:=a+1,,
  COBEGIN ⦃´I1⦄
       WHILE ¬´found
       INV ⦃´I1⦄
       DO ⦃a≤´x ∧ (´found ⟶ ´y≤a ∧ f(´y)=0) ∧ (a<´x ⟶ f(´x)≠0)⦄
          ⟨ ´x:=´x+1,,IF f(´x)=0 THEN  ´found:=True ELSE  SKIP FI⟩
       OD
       ⦃´I1 ∧ ´found⦄
  ∥
      ⦃´I2⦄
       WHILE ¬´found
       INV ⦃´I2⦄
       DO ⦃´y≤a+1 ∧ (´found ⟶ a<´x ∧ f(´x)=0) ∧ (´y≤a ⟶ f(´y)≠0)⦄
          ⟨ ´y:=(´y - 1),,IF f(´y)=0 THEN  ´found:=True ELSE  SKIP FI⟩
       OD
       ⦃´I2 ∧ ´found⦄
  COEND
  ⦃f(´x)=0 ∨ f(´y)=0⦄"
apply oghoare
apply auto
done
subsection ‹Producer/Consumer›
subsubsection ‹Previous lemmas›
lemma nat_lemma2: "⟦ b = m*(n::nat) + t; a = s*n + u; t=u; b-a < n ⟧ ⟹ m ≤ s"
proof -
  assume "b = m*(n::nat) + t" "a = s*n + u" "t=u"
  hence "(m - s) * n = b - a" by (simp add: diff_mult_distrib)
  also assume "… < n"
  finally have "m - s < 1" by simp
  thus ?thesis by arith
qed
lemma mod_lemma: "⟦ (c::nat) ≤ a; a < b; b - c < n ⟧ ⟹ b mod n ≠ a mod n"
apply(subgoal_tac "b=b div n*n + b mod n" )
 prefer 2  apply (simp add: div_mult_mod_eq [symmetric])
apply(subgoal_tac "a=a div n*n + a mod n")
 prefer 2
 apply(simp add: div_mult_mod_eq [symmetric])
apply(subgoal_tac "b - a ≤ b - c")
 prefer 2 apply arith
apply(drule le_less_trans)
back
 apply assumption
apply(frule less_not_refl2)
apply(drule less_imp_le)
apply (drule_tac m = "a" and k = n in div_le_mono)
apply(safe)
apply(frule_tac b = "b" and a = "a" and n = "n" in nat_lemma2, assumption, assumption)
apply assumption
apply(drule order_antisym, assumption)
apply(rotate_tac -3)
apply(simp)
done
subsubsection ‹Producer/Consumer Algorithm›