(* Author: Max Haslbeck *)
theory Nielson_VCG imports Nielson_Hoare begin
subsection "Verification Condition Generator"
text‹Annotated commands: commands where loops are annotated with
invariants.›
datatype acom =
Askip (‹SKIP›) |
Aassign vname aexp (‹(_ ::= _)› [1000, 61] 61) |
Aseq acom acom (‹_;;/ _› [60, 61] 60) |
Aif bexp acom acom (‹(IF _/ THEN _/ ELSE _)› [0, 0, 61] 61) |
Aconseq assn2 assn2 tbd acom
(‹({_'/_'/_}/ CONSEQ _)› [0, 0, 0, 61] 61)|
Awhile "(assn2)*((state→state)*(tbd))" bexp acom (‹({_}/ WHILE _/ DO _)› [0, 0, 61] 61)
notation com.SKIP (‹SKIP›)
text‹Strip annotations:›
fun strip :: "acom → com" where
"strip SKIP = SKIP" |
"strip (x ::= a) = (x ::= a)" |
"strip (C1;; C2) = (strip C1;; strip C2)" |
"strip (IF b THEN C1 ELSE C2) = (IF b THEN strip C1 ELSE strip C2)" |
"strip ({_/_/_} CONSEQ C) = strip C" |
"strip ({_} WHILE b DO C) = (WHILE b DO strip C)"
text "support of an expression"
subsubsection "support and supportE"
definition supportE :: "((char list → nat) → (char list → int) → nat) → string set" where
"supportE P = {x. ∃l1 l2 s. (∀y. y ≠ x ⟶ l1 y = l2 y) ∧ P l1 s ≠ P l2 s}"
lemma expr_lupd: "x ∉ supportE Q ==> Q (l(x:=n)) = Q l"
by(simp add: supportE_def fun_upd_other fun_eq_iff)
(metis (no_types, lifting) fun_upd_def)
lemma supportE_if: "supportE (λl s. if b s then A l s else B l s)
⊆ supportE A ∪ supportE B"
unfolding supportE_def apply(auto)
by metis+
lemma support_eq: "support (λl s. l x = E l s) ⊆ supportE E ∪ {x}"
unfolding support_def supportE_def
apply(auto)
apply blast
by metis
lemma support_impl_in: "G e ⟶ support (λl s. H e l s) ⊆ T
==> support (λl s. G e ⟶ H e l s) ⊆ T"
unfolding support_def apply(auto)
apply blast+ done
lemma support_supportE: "∧P e. support (λl s. P (e l) s) ⊆ supportE e"
unfolding support_def supportE_def
apply(rule subsetI)
apply(simp)
proof (clarify, goal_cases)
case (1 P e x l1 l2 s)
have P: "∀s. e l1 s = e l2 s ==> e l1 = e l2" by fast
show "∃l1 l2. (∀y. y ≠ x ⟶ l1 y = l2 y) ∧ (∃s. e l1 s ≠ e l2 s)"
apply(rule exI[where x=l1])
apply(rule exI[where x=l2])
apply(safe)
using 1 apply blast
apply(rule ccontr)
apply(simp)
using 1(2) P by force
qed
― ‹collects the logical variables in the Invariants and Loop Bodies as well as the annotated
assertions at CONSEQs of an annotated command›
fun varacom :: "acom → lvname set" where
"varacom (C1;; C2)= varacom C1 ∪ varacom C2"
| "varacom (IF b THEN C1 ELSE C2)= varacom C1 ∪ varacom C2"
| "varacom ({P/Qannot/_} CONSEQ C)= support P ∪ varacom C ∪ support Qannot"
| "varacom ({(I,(S,(E)))} WHILE b DO C) = support I ∪ varacom C"
| "varacom _ = {}"
text‹Weakest precondition from annotated commands:›
fun preT :: "acom → tbd → tbd" where
"preT SKIP e = e" |
"preT (x ::= a) e = (λs. e(s(x := aval a s)))" |
"preT (C1;; C2) e = preT C1 (preT C2 e)" |
"preT ({_/_/_} CONSEQ C) e = preT C e" |
"preT (IF b THEN C1 ELSE C2) e =
(λs. if bval b s then preT C1 e s else preT C2 e s)" |
"preT ({(_,(S,_))} WHILE b DO C) e = e o S"
lemma preT_linear: "preT C (%s. k * e s) = (%s. k * preT C e s)"
by (induct C arbitrary: e, auto)
fun postQ :: "acom → state → state" where (* seems to be forward?! *)
"postQ SKIP s = s" |
"postQ (x ::= a) s = s(x := aval a s)" |
"postQ (C1;; C2) s = postQ C2 (postQ C1 s)" |
"postQ ({_/_/_} CONSEQ C) s = postQ C s" |
"postQ (IF b THEN C1 ELSE C2) s =
(if bval b s then postQ C1 s else postQ C2 s)" |
"postQ ({(_,(S,_))} WHILE b DO C) s = S s"
lemma TQ: "preT C e s = e (postQ C s)"
apply(induct C arbitrary: e s) by (auto)
(* given a state, how often will a While loop be evaluated ? *)
function (domintros) times :: "state → bexp → acom → nat" where
"times s b C = (if bval b s then Suc (times (postQ C s) b C) else 0)"
apply(auto) done
lemma assumes I: "I z s" and
i: "∧s z. I (Suc z) s ==> bval b s ∧ I z (postQ C s)"
and ii: "∧s. I 0 s ==> ~ bval b s"
shows times_z: "times s b C = z"
proof -
have "I z s ==> times_dom (s, b, C) ∧ times s b C = z"
proof(induct z arbitrary: s)
case 0
have A: "times_dom (s, b, C)"
apply(rule times.domintros)
apply(simp add: ii[OF 0] ) done
have B: "times s b C = 0"
using times.psimps[OF A] by(simp add: ii[OF 0])
show ?case using A B by simp
next
case (Suc z)
from i[OF Suc(2)] have bv: "bval b s"
and g: "I z (postQ C s)" by simp_all
from Suc(1)[OF g] have p1: "times_dom (postQ C s, b, C)"
and p2: "times (postQ C s) b C = z" by simp_all
have A: "times_dom (s, b, C)"
apply(rule times.domintros) apply(rule p1) done
have B: "times s b C = Suc z"
using times.psimps[OF A] bv p2 by simp
show ?case using A B by simp
qed
then show "times s b C = z" using I by simp
qed
function (domintros) postQs :: "acom → bexp → state → state" where
"postQs C b s = (if bval b s then (postQs C b (postQ C s)) else s)"
apply(auto) done
fun postQz :: "acom → state → nat → state" where
"postQz C s 0 = s" |
"postQz C s (Suc n) = (postQz C (postQ C s) n)"
fun preTz :: "acom → tbd → nat → tbd" where
"preTz C e 0 = e" |
"preTz C e (Suc n) = preT C (preTz C e n)"
lemma TzQ: "preTz C e n s = e (postQz C s n)"
by (induct n arbitrary: s, simp_all add: TQ)
subsubsection ‹Weakest precondition from annotated commands:›
fun pre :: "acom → assn2 → assn2" where
"pre SKIP Q = Q" |
"pre (x ::= a) Q = (λl s. Q l (s(x := aval a s)))" |
"pre (C1;; C2) Q = pre C1 (pre C2 Q)" |
"pre ({P'/_/_} CONSEQ C) Q = P'" |
"pre (IF b THEN C1 ELSE C2) Q =
(λl s. if bval b s then pre C1 Q l s else pre C2 Q l s)" |
"pre ({(I,(S,(E)))} WHILE b DO C) Q = I"
lemma supportE_preT: "supportE (%l. preT C (e l)) ⊆ supportE e"
proof(induct C arbitrary: e)
case (Aif b C1 C2 e)
show ?case
apply(simp)
apply(rule subset_trans[OF supportE_if])
using Aif by fast
next
case (Awhile A y C e)
obtain I S E where A: "A= (I,S,E)" using prod_cases3 by blast
show ?case using A apply(simp) unfolding supportE_def
by blast
next
case (Aseq)
then show ?case by force
qed (simp_all add: supportE_def, blast)
lemma supportE_twicepreT: "supportE (%l. preT C1 (preT C2 (e l))) ⊆ supportE e"
by (rule subset_trans[OF supportE_preT supportE_preT])
lemma supportE_preTz: "supportE (%l. preTz C (e l) n) ⊆ supportE e"
proof (induct n)
case (Suc n)
show ?case
apply(simp)
apply(rule subset_trans[OF supportE_preT])
by fact
qed simp
lemma supportE_preTz_Un: (* like in support_wpw_Un *)
"supportE (λl. preTz C (e l) (l x)) ⊆ insert x (UN n. supportE (λl. preTz C (e l) n))"
apply(auto simp add: supportE_def subset_iff)
apply metis
done
lemma supportE_preTz2: "supportE (%l. preTz C (e l) (l x)) ⊆ insert x (supportE e)"
apply(rule subset_trans[OF supportE_preTz_Un])
using supportE_preTz by blast
lemma pff: "∧n. support (λl. I (l(x := n))) ⊆ support I - {x}"
unfolding support_def apply(auto) using fun_upd_apply apply smt
apply (smt fun_upd_apply) oops
lemma pff: "∧n. support (λl. I (l(x := n))) ⊆ support I"
unfolding support_def apply(auto) using fun_upd_apply apply smt
by (smt fun_upd_apply)
lemma supportAB: "support (λl s. A l s ∧ B s) ⊆ support A"
apply(rule subset_trans[OF support_and])
by (simp add: support_inv)
lemma "support (pre ({(I,(S,(E )))} WHILE b DO C) Q) ⊆ support I"
by (simp add: supportAB)
lemma support_pre: "support (pre C Q) ⊆ support Q ∪ varacom C"
proof (induct C arbitrary: Q)
case (Awhile A b C Q)
obtain I S E where A: "A= (I,(S,(E )))" using prod_cases3 by blast
have support_inv: "∧P. support (λl s. P s) = {}"
unfolding support_def by blast
show ?case unfolding A apply(simp) using supportAB by fast
next
case (Aseq C1 C2)
then show ?case by(auto)
next
case (Aif x C1 C2 Q)
have s1: "support (λl s. bval x s ⟶ pre C1 Q l s) ⊆ support Q ∪ varacom C1"
apply(rule subset_trans[OF support_impl]) by(rule Aif)
have s2: "support (λl s. ~ bval x s ⟶ pre C2 Q l s) ⊆ support Q ∪ varacom C2"
apply(rule subset_trans[OF support_impl]) by(rule Aif)
show ?case apply(simp)
apply(rule subset_trans[OF support_and])
using s1 s2 by blast
next
case (Aconseq x1 x2 x3 C)
then show ?case by(auto)
qed (auto simp add: support_def)
lemma finite_support_pre[simp]: "finite (support Q) ==> finite (varacom C) ==> finite (support (pre C Q))"
using finite_subset support_pre finite_UnI by metis
fun time :: "acom → tbd" where
"time SKIP = (%s. Suc 0)" |
"time (x ::= a) = (%s. Suc 0)" |
"time (C1;; C2) = (%s. time C1 s + preT C1 (time C2) s)" |
"time ({_/_/e} CONSEQ C) = e" |
"time (IF b THEN C1 ELSE C2) =
(λs. if bval b s then 1 + time C1 s else 1 + time C2 s)" |
"time ({(_,(E',(E )))} WHILE b DO C) = E"
lemma supportE_single: "supportE (λl s. P) = {}"
unfolding supportE_def by blast
lemma supportE_plus: "supportE (λl s. e1 l s + e2 l s) ⊆ supportE e1 ∪ supportE e2"
unfolding supportE_def apply(auto)
by metis
lemma supportE_Suc: "supportE (λl s. Suc (e1 l s)) = supportE e1"
unfolding supportE_def by (auto)
lemma supportE_single2: "supportE (λl . P) = {}"
unfolding supportE_def by blast
lemma supportE_time: "supportE (λl. time C) = {}"
using supportE_single2 by simp
lemma "∧s. (∀l. I (l(x:=0)) s) = (∀l. l x = 0 ⟶ I l s)"
apply(auto)
by (metis fun_upd_triv)
lemma "∧s. (∀l. I (l(x:=Suc (l x))) s) = (∀l. (∃n. l x = Suc n) ⟶ I l s)"
apply(auto)
proof (goal_cases)
case (1 s l n)
then have "∧l. I (l(x := Suc (l x))) s" by simp
from this[where l="l(x:=n)"]
have "I ((l(x:=n))(x := Suc ((l(x:=n)) x))) s" by simp
then show ?case using 1(2) apply(simp)
by (metis fun_upd_triv)
qed
text‹Verification condition:›
fun vc :: "acom → assn2 → bool" where
"vc SKIP Q = True" |
"vc (x ::= a) Q = True" |
"vc (C1 ;; C2) Q = ((vc C1 (pre C2 Q)) ∧ (vc C2 Q) )" |
"vc (IF b THEN C1 ELSE C2) Q = (vc C1 Q ∧ vc C2 Q)" |
"vc ({P'/Q/e'} CONSEQ C) Q' = (vc C Q ∧ (∃k>0. (∀l s. P' l s ⟶ time C s ≤ k * e' s ∧ (∀t. ∃l'. (pre C Q) l' s ∧ ( Q l' t ⟶ Q' l t) ))))" |
"vc ({(I,(S,(E)))} WHILE b DO C) Q =
((∀l s. (I l s ∧ bval b s ⟶ pre C I l s ∧ E s ≥ 1 + preT C E s + time C s
∧ S s = S (postQ C s)) ∧
(I l s ∧ ¬ bval b s ⟶ Q l s ∧ E s ≥ 1 ∧ S s = s) ) ∧
vc C I)"
lemma pre_mono:
"(∀l s. P l s ⟶ P' l s) ==> pre C P l s ==> pre C P' l s"
proof (induction C arbitrary: P P' l s)
case (Aseq C1 C2)
then have A: "pre C1 (pre C2 P) l s" by(simp)
from Aseq(2)[OF Aseq(3)] Aseq(1)[OF _ A]
show ?case by simp
next
case (Awhile A b C)
then obtain I S E where A: "A = (I,S,E )" using prod_cases3 by blast
from Awhile show ?case unfolding A by simp
qed simp_all
lemma vc_mono: "(∀l s. P l s ⟶ P' l s) ==> vc C P ==> vc C P'"
apply (induct C arbitrary: P P')
apply auto
subgoal using pre_mono by metis
subgoal using pre_mono by metis
done
subsubsection ‹Soundness:›
abbreviation "preSet U C l s == (Ball U (%u. case u of (x,e) → l x = preT C e s))"
abbreviation "postSet U l s == (Ball U (%u. case u of (x,e) → l x = e s))"
fun ListUpdate where
"ListUpdate f [] l = f"
| "ListUpdate f ((x,e)#xs) q = (ListUpdate f xs q)(x:=q e x)"
lemma allg:
assumes U2: "∧l s n x. x∈ fst ` upds ==> A (l(x := n)) = A l"
shows
"fst ` set xs ⊆ fst ` upds ==> A (ListUpdate l'' xs q) = A l''"
proof (induct xs)
case (Cons a xs)
obtain x e where axe: "a = (x,e)" by fastforce
have "A (ListUpdate l'' (a # xs) q)
= A ((ListUpdate l'' xs q)(x := q e x)) " unfolding axe by(simp)
also have
"… = A (ListUpdate l'' xs q) "
apply(rule U2)
using Cons axe by force
also have "… = A l'' "
using Cons by force
finally show ?case .
qed simp
fun ListUpdateE where
"ListUpdateE f [] = f"
| "ListUpdateE f ((x,v)#xs) = (ListUpdateE f xs )(x:=v)"
lemma ListUpdate_E: "ListUpdateE f xs = ListUpdate f xs (%e x. e)"
apply(induct xs) apply(simp_all)
subgoal for a xs apply(cases a) apply(simp) done
done
lemma allg_E: fixes A::assn2
assumes
" (∧l s n x. x ∈ fst ` upds ==> A (l(x := n)) = A l)" "fst ` set xs ⊆ fst ` upds"
shows "A (ListUpdateE f xs) = A f"
proof -
have " A (ListUpdate f xs (%e x. e)) = A f"
apply(rule allg)
apply fact+ done
then show ?thesis by(simp only: ListUpdate_E)
qed
lemma ListUpdateE_updates: "distinct (map fst xs) ==> x ∈ set xs ==> ListUpdateE l'' xs (fst x) = snd x"
proof (induct xs)
case Nil
then show ?case apply(simp) done
next
case (Cons a xs)
show ?case
proof (cases "fst a = fst x")
case True
then obtain y e where a: "a=(y,e)" by fastforce
with True have fstx: "fst x=y" by simp
from Cons(2,3) fstx a have a2: "x=a"
by force
show ?thesis unfolding a2 a by(simp)
next
case False
with Cons(3) have A: "x∈set xs" by auto
obtain y e where a: "a=(y,e)" by fastforce
from Cons(2) have B: "distinct (map fst xs)" by simp
from Cons(1)[OF B A] False
show ?thesis unfolding a by(simp)
qed
qed
lemma ListUpdate_updates: "x ∈ fst ` (set xs) ==> ListUpdate l'' xs (%e. l) x = l x"
proof(induct xs)
case Nil
then show ?case by(simp)
next
case (Cons a xs)
obtain q p where axe: "a = (p,q)" by fastforce
from Cons show ?case unfolding axe
apply(cases "x=p")
by(simp_all)
qed
abbreviation "lesvars xs == fst ` (set xs)"
fun preList where
"preList [] C l s = True"
| "preList ((x,e)#xs) C l s = (l x = preT C e s ∧ preList xs C l s)"
lemma preList_Seq: "preList upds (C1;; C2) l s = preList (map (λ(x, e). (x, preT C2 e)) upds) C1 l s"
proof (induct upds)
case Nil
then show ?case by simp
next
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a by (simp)
qed
lemma support_True[simp]: "support (λa b. True) = {}"
unfolding support_def
by fast
lemma support_preList: "support (preList upds C1) ⊆ lesvars upds"
proof (induct upds)
case Nil
then show ?case by simp
next
case (Cons a upds)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a apply (simp)
apply(rule subset_trans[OF support_and])
apply(rule Un_least)
subgoal apply(rule subset_trans[OF support_eq])
using supportE_twicepreT subset_trans supportE_single2 by simp
subgoal by auto
done
qed
lemma preListpreSet: "preSet (set xs) C l s ==> preList xs C l s"
proof (induct xs)
case Nil
then show ?case by simp
next
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a by (simp)
qed
lemma preSetpreList: "preList xs C l s ==> preSet (set xs) C l s"
proof (induct xs)
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a
by(simp)
qed simp
(* surprise. but makes sense, if the clauses are contradictory on the
left side, so are they on the right side *)
lemma preSetpreList_eq: "preList xs C l s = preSet (set xs) C l s"
proof (induct xs)
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a
by(simp)
qed simp
fun postList where
"postList [] l s = True"
| "postList ((x,e)#xs) l s = (l x = e s ∧ postList xs l s)"
lemma support_postList: "support (postList xs) ⊆ lesvars xs"
proof (induct xs)
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a
apply(simp) apply(rule subset_trans[OF support_and])
apply(rule Un_least)
subgoal apply(rule subset_trans[OF support_eq])
using supportE_twicepreT subset_trans supportE_single2 by simp
subgoal by(auto)
done
qed simp
lemma postpreList_inv: assumes "S s = S (postQ C s)"
shows "postList (map (λ(x, e). (x, λs. e (S s))) upds) l s = preList (map (λ(x, e). (x, λs. e (S s))) upds) C l s"
proof (induct upds)
case (Cons a upds)
obtain y e where axe: "a = (y,e)" by fastforce
from Cons show ?case unfolding axe apply(simp)
apply(simp only: TQ) using assms by auto
qed simp
lemma postList_preList: "postList (map (λ(x, e). (x, preT C e)) upds) l s = preList upds C l s"
proof (induct upds)
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a
by(simp)
qed simp
lemma postSetpostList: "postList xs l s ==> postSet (set xs) l s"
proof (induct xs)
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a
by(simp)
qed simp
lemma postListpostSet: "postSet (set xs) l s ==> postList xs l s"
proof (induct xs)
case (Cons a xs)
obtain y e where a: "a=(y,e)" by fastforce
from Cons show ?case unfolding a
by(simp)
qed simp
lemma ListAskip: "preList xs Askip l s = postList xs l s"
apply(induct xs)
apply(simp) by force
lemma SetAskip: "preSet U Askip l s = postSet U l s"
by simp
lemma ListAassign: "preList upds (Aassign x1 x2) l s = postList upds l (s[x2/x1])"
apply(induct upds)
apply(simp) by force
lemma SetAassign: "preSet U (Aassign x1 x2) l s = postSet U l (s[x2/x1])"
by simp
lemma ListAconseq: "preList upds (Aconseq x1 x2 x3 C) l s = preList upds C l s"
apply(induct upds)
apply(simp) by force
lemma SetAconseq: "preSet U (Aconseq x1 x2 x3 C) l s = preSet U C l s"
by simp
lemma ListAif1: "bval b s ==> preList upds (IF b THEN C1 ELSE C2) l s = preList upds C1 l s"
apply(induct upds)
apply(simp) by force
lemma SetAif1: "bval b s ==> preSet upds (IF b THEN C1 ELSE C2) l s = preSet upds C1 l s"
apply(simp) done
lemma ListAif2: "~ bval b s ==> preList upds (IF b THEN C1 ELSE C2) l s = preList upds C2 l s"
apply(induct upds)
apply(simp) by force
lemma SetAif2: "~ bval b s ==> preSet upds (IF b THEN C1 ELSE C2) l s = preSet upds C2 l s"
apply(simp) done
(*
In upds we collect pairs of logical variables and time expressions, these logical variables
are bound to the value of these expressions. postList upds C l s is an assertion stating that
for every (x,e) in upds, l x = e s; preList upds C l s does the same, but pulls the expression
e through the command c, i.e. stating for ever (x,e) in upds, l x = preT C e s.
we have to make sure, that no variable is assigned twice (the 5th premise), as well as they are
different from all the logical variables that occur in the annotated program C (4th premise)
we have to make sure that we can always choose new logical variables (premise 2, 3)
*)
lemma vc_sound: "vc C Q ==> finite (support Q) ==> finite (varacom C)
==> fst ` (set upds) ∩ varacom C = {} ==> distinct (map fst upds)
==> ⊨1 {%l s. pre C Q l s ∧ preList upds C l s} strip C { time C ⇓ %l s. Q l s ∧ postList upds l s}
∧ (∀l s. pre C Q l s ⟶ Q l (postQ C s))"
proof(induction C arbitrary: Q upds)
case (Askip Q upds)
then show ?case
apply(auto)
apply(rule weaken_post[where Q="%l s. Q l s ∧ preList upds Askip l s"])
apply(simp add: Skip) using ListAskip
by fast
next
case (Aassign x1 x2 Q upds)
then show ?case apply(safe) apply(auto simp add: Assign)[1]
apply(rule weaken_post[where Q="%l s. Q l s ∧ postList upds l s"])
apply(simp only: ListAassign)
apply(rule Assign) apply simp
apply(simp only: postQ.simps pre.simps) done
next
case (Aif b C1 C2 Q upds )
then show ?case apply(auto simp add: Assign)
apply(rule If2[where e="λa. if bval b a then time C1 a else time C2 a"])
subgoal
apply(simp cong: rev_conj_cong)
apply(rule ub_cost[where e'="time C1"])
apply(simp) apply(auto)[1]
apply(rule strengthen_pre[where P="%l s. pre C1 Q l s ∧ preList upds C1 l s"])
using ListAif1
apply fast
apply(rule Aif(1)[THEN conjunct1])
apply(auto)
done
subgoal
apply(simp cong: rev_conj_cong)
apply(rule ub_cost[where e'="time C2"]) (* k=1 and *)
apply(simp) apply(auto)[1]
apply(rule strengthen_pre[where P="%l s. pre C2 Q l s ∧ preList upds C2 l s"])
using ListAif2
apply fast
apply(rule Aif(2)[THEN conjunct1])
apply(auto)
done
apply auto apply fast+ done
next
case (Aconseq P' Qannot eannot C Q upds)
then obtain k where k: "k>0" and ih1: "vc C Qannot"
and ih1': " (∀l s. P' l s ⟶ time C s ≤ k * eannot s ∧ (∀t. ∃l'. pre C Qannot l' s ∧ (Qannot l' t ⟶ Q l t)))"
by auto
have ih2': "∀l s. pre C Qannot l s ⟶ Qannot l (postQ C s)"
apply(rule Aconseq(1)[THEN conjunct2]) using Aconseq(2-6) by auto
have G1: "⊨1 {λl s. P' l s ∧ preList upds ({P'/Qannot/eannot} CONSEQ C) l s} strip C
{ eannot ⇓ λl s. Q l s ∧ postList upds l s}"
proof (rule conseq[rotated])
show "⊨1 {λl s. pre C Qannot l s ∧ preList upds C l s} strip C { time C ⇓ λl s. Qannot l s ∧ postList upds l s}"
apply(rule Aconseq(1)[THEN conjunct1])
using Aconseq(2-6) by auto
next
show "∃k>0. ∀l s. P' l s ∧ preList upds ({P'/Qannot/eannot} CONSEQ C) l s ⟶
time C s ≤ k * eannot s ∧
(∀t. ∃l'. (pre C Qannot l' s ∧ preList upds C l' s) ∧
(Qannot l' t ∧ postList upds l' t ⟶ Q l t ∧ postList upds l t))"
proof(rule exI[where x=k], safe)
fix l s
assume P': "P' l s" and prelist: "preList upds ({P'/Qannot/eannot} CONSEQ C) l s"
then show "time C s ≤ k * eannot s" using ih1' by simp
fix t
― ‹we now have to construct a logical environment, that both
* satisfies the annotated postcondition Qannot (we obtain it from the first IH)
* lets the updates come true (we have to show that resetting these logical variables
does not interfere with the other variables)›
from ih1' P' have satQan:"(∃l'. pre C Qannot l' s ∧ (Qannot l' t ⟶ Q l t))" by simp
then obtain l' where i': "pre C Qannot l' s" and ii': "(Qannot l' t ⟶ Q l t)" by blast
let ?upds' = "(map (%(x,e). (x,preT C e s)) upds)"
let ?l'' = "(ListUpdateE l' ?upds')"
{
fix l s n x
assume "x ∈ fst ` (set upds)"
then have "x ∉ support (pre C Qannot)" using Aconseq(5) support_pre by auto
from assn2_lupd[OF this] have "pre C Qannot (l(x := n)) = pre C Qannot l" .
} note U2=this
{
fix l s n x
assume "x ∈ fst ` (set upds)"
then have "x ∉ support Qannot" using Aconseq(5) by auto
from assn2_lupd[OF this] have "Qannot (l(x := n)) = Qannot l" .
} note K2=this
have "pre C Qannot ?l'' = pre C Qannot l' "
apply(rule allg_E[where ?upds="set upds"]) apply(rule U2) by force+
with i' have i'': "pre C Qannot ?l'' s" by simp
have "Qannot ?l'' = Qannot l'"
apply(rule allg_E[where ?upds="set upds"]) apply(rule K2) by force+
then have K: "(%l' s. Qannot l' t ⟶ Q l t) ?l'' s = (%l' s. Qannot l' t ⟶ Q l t) l' s"
by simp
with ii' have ii'': "(Qannot ?l'' t ⟶ Q l t)" by simp
have xs_upds: "map fst ?upds' = map fst upds"
by auto
have resets: "∧x. x ∈ set ?upds' ==> ListUpdateE l' ?upds' (fst x) = snd x" apply(rule ListUpdateE_updates)
apply(simp only: xs_upds) using Aconseq(6) apply simp
apply(simp) done
have A: "preList upds C ?l'' s"
proof (rule preListpreSet,safe,goal_cases)
case (1 x e)
then have "(x, preT C e s) ∈ set ?upds'"
by fastforce
from resets[OF this, simplified]
show ?case .
qed
have B: "Qannot ?l'' t ==> postList upds ?l'' t ==> postList upds l t"
proof (rule postListpostSet, safe, goal_cases)
case (1 x e)
from postSetpostList[OF 1(2)] have g: "postSet (set upds) ?l'' t" .
with 1(3) have A: "?l'' x = e t"
by fast
from 1(3) resets[of "(x,preT C e s)"] have B: "?l'' x = snd (x, preT C e s)"
by fastforce
from A B have X: "e t = preT C e s" by fastforce
from preSetpreList[OF prelist] have "preSet (set upds) ({P'/Qannot/eannot} CONSEQ C) l s" .
with 1(3) have Y: "l x = preT C e s" apply(simp) by fast
from X Y show ?case by simp
qed
show "∃l'. (pre C Qannot l' s ∧ preList upds C l' s) ∧
(Qannot l' t ∧ postList upds l' t ⟶ Q l t ∧ postList upds l t)"
apply(rule exI[where x="?l''"], safe)
using i'' A ii'' B by auto
qed fact
qed
have G2: "∧l s. P' l s ==> Q l (postQ C s)"
proof -
fix l s
assume "P' l s"
with ih1' ih2' show "Q l (postQ C s)" by blast
qed
show ?case using G1 G2 by auto
next
case (Aseq C1 C2 Q upds)
let ?P = "(λl s. pre (C1;; C2) Q l s ∧ preList upds (C1;;C2) l s )"
let ?P' = "support Q ∪ varacom C1 ∪ varacom C2 ∪ lesvars upds"
have finite_varacom: "finite (varacom (C1;; C2))" by fact
have sup_L: "support (preList upds (C1;;C2)) ⊆ lesvars upds"
apply(rule support_preList) done
― ‹choose a fresh logical variable ?y in order to pull through the cost of the second command›
let ?y = "SOME x. x ∉ ?P'"
have fP': "finite (?P')" using finite_varacom Aseq(4,5) apply simp done
from fP' have "∃x. x ∉ ?P'" using infinite_UNIV_listI
using ex_new_if_finite by metis
hence ynP': "?y ∉ ?P'" by (rule someI_ex)
hence ysupC1: "?y ∉ varacom C1" using support_pre by auto
have sup_B: "support ?P ⊆ ?P'"
apply(rule subset_trans[OF support_and]) apply simp using support_pre sup_L by blast
― ‹we show the first goal: we can deduce the desired Hoare Triple›
have C1: "⊨1 {λl s. pre (C1;; C2) Q l s ∧ preList upds (C1;; C2) l s} strip C1;; strip C2
{ time (C1;; C2) ⇓ λl s. Q l s ∧ postList upds l s}"
proof (rule Seq[rotated])
― ‹start from the back: we can simply use the IH for C2,
and solve the side conditions automatically›
show "⊨1 {(%l s. pre C2 Q l s ∧ preList upds C2 l s )} strip C2 { time C2 ⇓ (%l s. Q l s ∧ postList upds l s)}"
apply(rule Aseq(2)[THEN conjunct1])
using Aseq(3-7) by auto
next
― ‹prepare the new updates: pull them through C2 and save the new execution time of C2 in ?y›
let ?upds = "map (λa. case a of (x,e) → (x, preT C2 e )) upds"
let ?upds' = "(?y,time C2)#?upds"
have dst_upds': "distinct (map fst ?upds')"
using ynP' Aseq(7) apply simp apply safe
using image_iff apply fastforce by (simp add: case_prod_beta' distinct_conv_nth)
― ‹now use the first induction hypothesis (specialised with the augmented upds list, and the
weakest precondition of Q through C as post condition)›
have IH1s: "⊨1 {λl s. pre C1 (pre C2 Q) l s ∧ preList ?upds' C1 l s} strip C1
{ time C1 ⇓ λl s. pre C2 Q l s ∧ postList ?upds' l s}"
apply(rule Aseq(1)[THEN conjunct1])
using Aseq(3-7) ysupC1 dst_upds' by auto
― ‹glue it together with a consequence rule, side conditions are automatic›
show " ⊨1 {λl s. (pre (C1;; C2) Q l s ∧ preList upds (C1;; C2) l s) ∧ l ?y = preT C1 (time C2) s} strip C1
{ time C1 ⇓ λl s. (λl s. pre C2 Q l s ∧ preList upds C2 l s) l s ∧ time C2 s ≤ l ?y}"
apply(rule conseq_old[OF _ IH1s])
by (auto simp: preList_Seq postList_preList)
next
― ‹solve some side conditions showing that, ?y is indeed fresh›
show "?y ∉ support ?P"
using sup_B ynP' by auto
have F: "support (preList upds C2) ⊆ lesvars upds"
apply(rule support_preList) done
have "support (λl s. pre C2 Q l s ∧ preList upds C2 l s) ⊆ ?P'"
apply(rule subset_trans[OF support_and]) using F support_pre by blast
with ynP'
show "?y ∉ support (λl s. pre C2 Q l s ∧ preList upds C2 l s)" by blast
qed simp
― ‹we show the second goal: weakest precondition implies, that
Q holds after the execution of C1 and C2›
have C2: "∧l s. pre (C1;; C2) Q l s ==> Q l (postQ (C1;; C2) s)"
proof -
fix l s
assume p: "pre (C1;; C2) Q l s"
have A: "∀l s. pre C1 (pre C2 Q ) l s ⟶ pre C2 Q l (postQ C1 s)"
apply(rule Aseq(1)[where upds="[]", THEN conjunct2])
using Aseq by auto
have B: "(∀l s. pre C2 Q l s ⟶ Q l (postQ C2 s))"
apply(rule Aseq(2)[where upds="[]", THEN conjunct2])
using Aseq by auto
from p A B show "Q l (postQ (C1;; C2) s)" by simp
qed
show ?case using C1 C2 by simp
next
case (Awhile A b C Q upds)
― ‹Let us first see, what we got from the induction hypothesis:›
obtain I S E where [simp]: "A = (I,(S,(E)))" using prod_cases3 by blast
with ‹vc (Awhile A b C) Q› have "vc (Awhile (I,S,E) b C) Q" by blast
then have vc: "vc C I" and pre2: "∧l s. I l s ==> ¬ bval b s ==> Q l s ∧ 1 ≤ E s ∧ S s = s"
and IQ2: "∧l s. I l s ==> bval b s ==>
pre C I l s
∧ 1 + preT C E s + time C s ≤ E s ∧ S s = S (postQ C s)" by auto
― ‹the logical variable x represents the number of loop unfoldings›
from IQ2 have IQ_in: "∧l s. I l s ==> bval b s ==> S s = S (postQ C s)" by auto
have inv_impl: "∧l s. I l s ==> bval b s ==> pre C I l s" using IQ2 by auto
have yC: " lesvars upds ∩ varacom C = {}" using Awhile(5) by auto
let ?upds = "map (%(x,e). (x, %s. e (S s))) upds"
let ?INV = "%l s. I l s ∧ postList ?upds l s"
have "lesvars upds ∩ support I = {}" using Awhile(5) by auto
― ‹we need a fresh variable ?z to remember the time bound of the tail of the loop›
let ?P="lesvars upds ∪ varacom ({A} WHILE b DO C)"
let ?z="SOME z::lvname. z ∉ ?P"
have "finite ?P" using Awhile by auto
hence "∃z. z∉?P" using infinite_UNIV_listI
using ex_new_if_finite by metis
hence znP: "?z ∉ ?P" by (rule someI_ex)
from znP have (* znx: "?z\<noteq>x"
and *) zny: "?z ∉ lesvars upds"
and zI: "?z ∉ support I"
and blb: "?z ∉ varacom C" by (simp_all)
from Awhile(4,6) have 23: "finite (varacom C)"
and 26: "finite (support I)" by auto
have "∀l s. pre C I l s ⟶ I l (postQ C s)"
apply(rule Awhile(1)[THEN conjunct2]) by(fact)+
hence step: "∧l s. pre C I l s ==> I l (postQ C s)" by simp
― ‹we adapt the updates, by pulling them through the loop body
and remembering the time bound of the tail of the loop›
let ?upds = "map (λ(x, e). (x, λs. e (S s))) upds"
have fua: "lesvars ?upds = lesvars upds"
by force
let ?upds' = "(?z,E) # ?upds"
have g: "∧e. e ∘ S = (%s. e (S s))" by auto
― ‹show that the Hoare Rule is derivable›
have G1: "⊨1 {λl s. I l s ∧ preList upds ({(I, S, E)} WHILE b DO C) l s} WHILE b DO strip C
{ E ⇓ λl s. Q l s ∧ postList upds l s}"
proof(rule conseq_old)
show "⊨1 {λl s. I l s ∧ postList ?upds l s} WHILE b DO strip C
{ E ⇓ λl s. (I l s ∧ postList ?upds l s) ∧ ¬bval b s }"
― ‹We use the While Rule and then have to show, that ...›
proof(rule While, goal_cases)
― ‹A) the loop body preserves the loop invariant›
have "lesvars ?upds' ∩ varacom C = {}"
using yC blb by(auto)
have z: "(fst ∘ (λ(x, e). (x, λs. e (S s)))) = fst" by auto
have "distinct (map fst ?upds')"
using Awhile(6) zny by (auto simp add: z)
― ‹for showing preservation of the invariant, use the consequence rule ...›
show "⊨1 {λl s. (I l s ∧ postList ?upds l s) ∧ bval b s ∧ preT C E s = l ?z}
strip C { time C ⇓ λl s. (I l s ∧ postList ?upds l s) ∧ E s ≤ l ?z}"
proof (rule conseq_old)
― ‹... and employ the induction hypothesis, ...›
show " ⊨1 {λl s. pre C I l s ∧ preList ?upds' C l s} strip C
{ time C ⇓ λl s. I l s ∧ postList ?upds' l s}"
apply(rule Awhile.IH[THEN conjunct1]) by fact+
next
― ‹finally we have to prove the side condition.›
show "∃k>0. ∀l s. (I l s ∧ postList ?upds l s) ∧ bval b s ∧ preT C E s = l ?z
⟶ (pre C I l s ∧ preList ?upds' C l s) ∧ time C s ≤ k * time C s"
apply(rule exI[where x=1]) apply(simp)
proof (safe, goal_cases)
case (2 l s)
note upds_invariant=postpreList_inv[OF IQ_in[OF 2(1)]]
from 2 upds_invariant show ?case by auto
next
case (1 l s) then show ?case using inv_impl by auto
qed
qed auto
next
― ‹B) the invariant with number of loop unfoldings greater than 0 implies true loop guard
and running time is correctly bounded›
show "∀l s. bval b s ∧ I l s ∧ postList ?upds l s ⟶ 1 + preT C E s + time C s ≤ E s"
proof (clarify, goal_cases)
case (1 l s)
show ?case using IQ2 1(1,2) by auto
qed
next
― ‹C) the invariant with number of loop unfoldings equal to 0 implies false loop guard
and running time is correctly bounded›
show "∀l s. ¬ bval b s ∧ I l s ∧ postList ?upds l s ⟶ 1 ≤ E s"
proof (clarify, goal_cases)
case (1 l s)
then show ?case
using pre2 1(2) by auto
qed
next
― ‹D) ?z is indeed a fresh variable›
have pff: "?z ∉ lesvars ?upds" apply(simp only: fua) by fact
have "support (λl s. I l s ∧ postList ?upds l s) ⊆ support I ∪ support (postList ?upds)"
by(rule support_and)
also have "support (postList ?upds) ⊆ lesvars ?upds"
apply(rule support_postList) done
finally
have "support (λl s. I l s ∧ postList ?upds l s) ⊆ support I ∪ lesvars ?upds"
by blast
thus "?z ∉ support (λl s. I l s ∧ postList ?upds l s)"
apply(rule contra_subsetD)
using zI pff by(simp)
qed
next
show "∃k>0. ∀l s. I l s ∧ preList upds ({(I, S, E)} WHILE b DO C) l s ⟶
(I l s ∧ postList (map (λ(x, e). (x, λs. e (S s))) upds) l s) ∧ E s ≤ k * E s"
apply(rule exI[where x=1]) apply(auto) apply(simp only: postList_preList[symmetric] ) apply (auto)
apply(simp only: g)
done
next
show "∀l s. (I l s ∧ postList (map (λ(x, e). (x, λs. e (S s))) upds) l s) ∧ ¬ bval b s ⟶ Q l s ∧ postList upds l s"
using pre2 by(induct upds, auto)
qed
have G2: "∧l s. pre ({A} WHILE b DO C) Q l s ==> Q l (postQ ({A} WHILE b DO C) s)"
proof -
fix l s
assume "pre ({A} WHILE b DO C) Q l s"
then have I: "I l s" by simp
{ fix n
have "E s = n ==> I l s ==> Q l (postQ ({A} WHILE b DO C) s)"
proof (induct n arbitrary: s l rule: less_induct)
case (less n)
then show ?case
proof (cases "bval b s")
case True
with less IQ2 have "pre C I l s" and S: "S s = S (postQ C s)" and t: "1 + preT C E s + time C s ≤ E s" by auto
with step have I': "I l (postQ C s)" and "1 + E (postQ C s) + time C s ≤ E s" using TQ by auto
with less have "E (postQ C s) < n" by auto
with less(1) I' have "Q l (postQ ({A} WHILE b DO C) (postQ C s))" by auto
with step show ?thesis using S by simp
next
case False
with pre2 less(3) have "Q l s" "S s = s" by auto
then show ?thesis by simp
qed
qed
}
with I show "Q l (postQ ({A} WHILE b DO C) s)" by simp
qed
show ?case using G1 G2 by auto
qed
corollary vc_sound':
assumes "vc C Q"
"finite (support Q)" "finite (varacom C)"
"∀l s. P l s ⟶ pre C Q l s"
shows "⊨1 {P} strip C {time C ⇓ Q}"
proof -
show ?thesis
apply(rule conseq_old)
prefer 2 apply(rule vc_sound[where upds="[]", OF assms(1-3), THEN conjunct1])
using assms(4) apply auto
done
qed
lemma preT_constant: "preT C (%_. a) = (%_. a)"
apply(induct C) by (auto)
corollary vc_sound'':
"[ vc C Q; (∃k>0. ∀l s. P l s ⟶ pre C Q l s ∧ time C s ≤ k * e s);
finite (support Q); finite (varacom C)] ==> ⊨1 {P} strip C {e ⇓ Q}"
apply(rule ub_cost[where e'="time C"])
apply(auto)
apply(rule vc_sound') by auto
subsubsection ‹Completeness:›
lemma vc_complete:
"⊨1 {P} c { e ⇓ Q} ==> ∃C. strip C = c ∧ vc C Q
∧ (∀l s. P l s ⟶ pre C Q l s ∧ Q l (postQ C s))
∧ (∃k. ∀l s. P l s ⟶ time C s ≤ k * e s) "
(is "_ ==> ∃C. ?G P c Q C e")
proof (induction rule: hoare1.induct )
case Skip
show ?case (is "∃C. ?C C")
proof show "?C Askip" by auto
qed
next
case (Assign P a x )
show ?case (is "∃C. ?C C")
proof show "?C(Aassign x a)" apply (simp del: fun_upd_apply) apply(auto) done qed
next
case (Seq P x e2' c1 e1 Q e2 c2 R e)
from Seq.IH(1) obtain C1 where "?G (λl s. P l s ∧ l x = e2' s) c1 (λa b. Q a b ∧ e2 b ≤ a x) C1 e1 " by blast
then obtain k where ih1: "strip C1 = c1"
"vc C1 (λa b. Q a b ∧ e2 b ≤ a x)"
"∧l s. P l s ==> l x = e2' s ==> pre C1 (λla sa. (Q la sa ∧ e2 sa ≤ la x)) l s"
"(∀l s. P l s ∧ l x = e2' s ⟶ time C1 s ≤ k * e1 s)"
"∧l s. P l s ==> l x = e2' s ==> Q l (postQ C1 s) ∧ e2 (postQ C1 s) ≤ l x"
apply auto done
from Seq.IH(2) obtain C2 where ih2: "?G Q c2 R C2 e2 " by blast
then obtain k2 where ih2: "strip C2 = c2"
"vc C2 R"
"(∧l s. Q l s ==> pre C2 R l s)"
"(∀l s. Q l s ⟶ time C2 s ≤ k2 * e2 s)"
"∧l s . Q l s ==> R l (postQ C2 s)" apply auto done
show ?case (is "∃C. ?C C")
proof
show "?C(Aseq (Aconseq P Q (time C1) C1) C2)" (* with Q being (\<lambda>la sa. (Q la sa \<and> e2 sa \<le> la x)) some less mono is needed *)
proof (safe, goal_cases)
case 1
then show ?case apply(simp add: ih1(1) ih2(1)) done
next
case 2
then show ?case apply(simp) apply(safe)
subgoal apply(rule vc_mono) prefer 2 apply (rule ih1(2)) apply(auto) done
subgoal apply(rule exI[where x=1]) apply safe
subgoal by(auto)
subgoal for l s t
apply(rule exI[where x="l(x:= e2' s)"])
apply(safe)
subgoal apply(rule pre_mono) prefer 2 apply (rule ih1(3))
apply(subst assn2_lupd) using Seq(3) by auto
subgoal apply(rule ih2(3)) using assn2_lupd[OF Seq(4)] by auto
done
done
subgoal by (rule ih2(2))
done
next
case (3 l s)
then show ?case apply(simp) done
next
case (4 l s)
from 4 have "P (l(x:=e2' s)) s" using assn2_lupd[OF Seq(3)] by simp
with ih1(5)[where l="l(x:=e2' s)"]
have "Q (l(x := e2' s)) (postQ C1 s)" by simp
then have "Q l (postQ C1 s)" using assn2_lupd[OF Seq(4)] by simp
with ih2(3) have "Q l (postQ C1 s)" by simp
with ih2(5)
show ?case apply(auto) done
next
case 5
from ih1(4) have
gg: "∧l s. [P l s; e2' s = l x] ==> time C1 s ≤ k * e1 s" by auto
show ?case
proof (rule exI[where x="(max k k2)"], safe, goal_cases)
case (1 l s)
have xnP: "x ∉ support P" by fact
have 41: "P (l(x := e2' s)) s"
apply(subst assn2_lupd)
apply(fact xnP)
apply(fact 5) done
have A: " time C1 s ≤ k * e1 s"
apply(rule gg[where l="l(x:=e2' s)"])
apply(rule 41)
apply(simp) done
have B: "preT C1 (time C2) s ≤ k2 * e2' s"
proof -
from 1 have "P (l(x := e2' s)) s" using assn2_lupd[OF xnP] by simp
have F: "Q (l(x:=e2' s)) (postQ C1 s) ∧ e2 (postQ C1 s) ≤ (l(x:=e2' s)) x"
apply(rule ih1(5)[where l="l(x:=e2' s)" and s=s])
apply(fact)
apply(simp) done
then have " time C2 (postQ C1 s) ≤ k2 * e2 (postQ C1 s)" using ih2(4) by auto
with F have "time C2 (postQ C1 s) ≤ k2 * e2' s"
using order_subst1 by fastforce
then show "preT C1 (time C2) s ≤ k2 * e2' s" using TQ by simp
qed
have "time C1 s + preT C1 (time C2) s ≤ k * e1 s + k2 * e2' s" using A B by linarith
also have "… ≤ (max k k2) * e1 s + (max k k2) * e2' s"
using nat_mult_max_left by auto
also have "… = (max k k2) * (e1 s + e2' s)" by algebra
also have "… ≤ (max k k2) * e s" using Seq(5)[OF 1] by auto
finally
have "time C1 s + preT C1 (time C2) s ≤ (max k k2) * e s" .
then show ?case
by auto
qed
qed
qed
next
case (If P b c1 e1 Q c2)
from If.IH(1) obtain C1 where "?G (λl s. P l s ∧ bval b s) c1 Q C1 e1"
by blast
then obtain k1 where ih1: " strip C1 = c1 ∧ vc C1 Q ∧ (∀l s. P l s ∧ bval b s ⟶ pre C1 Q l s ∧ Q l (postQ C1 s)) ∧ ( ∀l s. P l s ∧ bval b s ⟶ time C1 s ≤ k1 * e1 s) "
by blast
from If.IH(2) obtain C2 where "?G (λl s. P l s ∧ ¬bval b s) c2 Q C2 e1"
by blast
then obtain k2 where ih2: " strip C2 = c2 ∧ vc C2 Q ∧ (∀l s. P l s ∧ ¬bval b s ⟶ pre C2 Q l s ∧ Q l (postQ C2 s)) ∧ ( ∀l s. P l s ∧ ¬bval b s ⟶ time C2 s ≤ k2 * e1 s )"
by blast
define k' where "k' == max (k1+1) (k2+1)"
show ?case (is "∃C. ?C C")
proof
show "?C(Aif b C1 C2)"
apply(safe)
prefer 5
apply(rule exI[where x="k'"]) apply(safe)
subgoal for l s apply(auto)
proof(goal_cases)
case 1
with ih1 have "time C1 s ≤ k1 * e1 s" by blast
then have "Suc (time C1 s) ≤ 1 + k1 * e1 s" by auto
also have "… ≤ k' + k1 * e1 s" unfolding k'_def by(auto)
also have "… ≤ k' + k' * e1 s" unfolding k'_def
by (simp add: max_def)
finally show ?case .
next
case 2
with ih2 have "time C2 s ≤ k2 * e1 s" by blast
then have "Suc (time C2 s) ≤ 1 + k2 * e1 s" by auto
also have "… ≤ k' + k2 * e1 s" unfolding k'_def by(auto)
also have "… ≤ k' + k' * e1 s" unfolding k'_def
by (simp add: max_def)
finally show ?case .
qed
using ih1 ih2 apply(simp)
using ih1 ih2 apply(auto)
done
qed
next
case (While P b e' y c e'' e)
have supportPre: "support (λl s. P l s ∧ bval b s ∧ e' s = l y) ⊆ support P ∪ {y}"
using support_and support_single by fast
from While.IH obtain C where
ih: "?G (λl s. P l s ∧ bval b s ∧ e' s = l y) c (λa b. P a b ∧ e b ≤ a y) C e''"
using supportPre by blast
then obtain k where ih2: "vc C (λa b. P a b ∧ e b ≤ a y)"
"∧l s. [ P l s ; bval b s ; e' s = l y ] ==> pre C (λla sa. (P la sa ∧ e sa ≤ la y)) l s"
"∧l s. [ P l s ; bval b s ; e' s = l y ] ==> time C s ≤ k * e'' s "
"∧l s.[ P l s ; bval b s ; e' s = l y] ==> P l (postQ C s) ∧ e (postQ C s) ≤ l y"
by fast
let ?S = "postQs C b"
{
fix l s n
have "e s = n ==> P l s ==> postQs_dom (C, b, s) ∧ P l (?S s) ∧ ~ bval b (?S s)"
proof (induct n arbitrary: l s rule: less_induct)
case (less x)
show ?case
proof (cases "bval b s")
case True
with While(2) less(3) have "1 + e' s + e'' s ≤ e s" by auto
then have e'e: "e' s < e s" by simp
have "P (l(y:=e' s)) s" using less(3) assn2_lupd[OF While(4)] by simp
from ih2(4)[OF this] True have ee': "e (postQ C s) ≤ e' s" and P': "P (l(y := e' s)) (postQ C s)" by auto
from P' have P'': "P l (postQ C s)" using less(3) assn2_lupd[OF While(4)] by simp
from ee' e'e less(2) have "e (postQ C s) < x" by auto
from less(1)[OF this _ P''] have d: "postQs_dom (C, b, postQ C s)"
and p: "P l (postQs C b (postQ C s))"
and b: "¬ bval b (postQs C b (postQ C s))" by auto
have d': "postQs_dom (C, b, s)"
by (simp add: d postQs.domintros)
have p': " P l (postQs C b s) "
using True d p postQs.domintros postQs.psimps by fastforce
have b': "¬ bval b (postQs C b s)"
by (metis b d postQs.domintros postQs.pelims)
from d' p' b' show ?thesis by auto
next
case False
then have 1: "postQs_dom (C, b, s)"
using postQs.domintros by blast
then have 2: "?S s = s" using postQs.psimps False by force
from 1 2 less(3) False show ?thesis by simp
qed
qed
}
then have Pdom: "∧l s. P l s ==> postQs_dom (C, b, s) ∧ P l (?S s) ∧ ~ bval b (?S s)" by simp
have S1: "∧l s. P l s ==> P l (?S s)" using Pdom by simp
have S2: "∧l s. P l s ==> ~ bval b (?S s)" using Pdom by simp
have S3: "∧l s. P l s ==> bval b s ==> ?S s = ?S (postQ C s)" using postQs.psimps Pdom by simp
have S4: "∧l s. P l s ==> ¬ bval b s ==> ?S s = s" using postQs.psimps Pdom by simp
let ?w = "{(P,?S,(%s. max k 1 * e s))} WHILE b DO (Aconseq (λl s. P l s ∧ bval b s) (λla sa. P la sa ∧ e sa ≤ la y) (time C) C)"
show ?case (is "∃C. ?C C")
proof
show "?C ?w"
proof (safe, goal_cases)
case 1
then show ?case using ih by(simp)
next
case 2
then show ?case
proof(simp, safe, goal_cases)
case (1 l s)
from 2 have z: "P (l(y := e' s)) s "
using 1 assn2_lupd[OF While(4)] by metis
from ih2(3)[where l="l(y := e' s)" and s=s]
have A: " time C s ≤ k * e'' s " using 1 z by(simp)
from ih2(4)[where l="l(y := e' s)" and s=s]
have "e (postQ C s) ≤ (l(y := e' s)) y" apply(simp) using 1 z by(simp)
then have "e (postQ C s) ≤ e' s" by simp
with TQ have B: "preT C e s ≤ e' s" by simp
let ?eskal = "(λs. max k (Suc 0) * e s)"
have "preT C (λs. max k (Suc 0) * e s) s = max k (Suc 0) * preT C e s"
using preT_linear by simp
with B have B: "preT C ?eskal s ≤ max k (Suc 0) * e' s" by auto
from While.hyps(2) 1 have C: "1 + e' s + e'' s ≤ e s" by auto
have "Suc (preT C ?eskal s + time C s) ≤ 1 + (max k 1) * e' s + k * e'' s"
using A B by linarith
also have "… ≤ (max k 1) + (max k 1) * e' s + (max k 1) * e'' s"
using nat_mult_max_left by auto
also have "… = (max k 1) * (1 + e' s + e'' s)"
by algebra
also have "… ≤ (max k 1) * e s"
using C by (metis mult.assoc mult_le_mono2)
finally have "Suc (preT C ?eskal s + time C s) ≤ ((max k 1) ) * e s" .
thus ?case by auto
next
case (3 l s)
with While.hyps(3) show ?case by auto
next
case 5
then show ?case
apply(rule vc_mono)
prefer 2 apply(fact ih2(1)) by auto
next
case 6
show ?case apply(rule exI[where x="1"]) apply(safe)
subgoal by simp
subgoal for l s t apply(rule exI[where x="l(y:=e' s)"])
proof (safe)
assume 8: "P l s" and b: " bval b s"
then have "P (l(y := e' s)) s" using assn2_lupd[OF While(4)] by metis
with b ih2(2) show "pre C (λla sa. P la sa ∧ e sa ≤ la y) (l(y := e' s)) s"
apply(auto) done
fix t
assume "P (l(y := e' s)) t"
thus "P l t" using assn2_lupd[OF While(4)] by simp
qed
done
qed (simp_all add: S4 S3)
next
case 6
show ?case apply(rule exI[where x="k+1"]) by auto
qed (simp_all add: S1 S2)
qed
next
case (conseq P' e e' P Q Q' c)
then obtain C k where C: "strip C = c"
"vc C Q"
"(∀l s . P l s ⟶ pre C Q l s )"
"(∀l s . P l s ⟶ Q l (postQ C s))"
"(∀l s. P l s ⟶ time C s ≤ k * e s)" by metis
from conseq(1) obtain k2 where cons: " ∀l s. P' l s ⟶ e s ≤ k2 * e' s ∧ (∀t. ∃l'. P l' s ∧ (Q l' t ⟶ Q' l t))" by auto
show ?case
apply(rule exI[where x="Aconseq P' Q (time C) C"])
apply(safe)
subgoal apply(simp) by(fact)
subgoal apply(simp)
apply(safe)
subgoal using C(2)
apply(fast) done
subgoal
apply(rule exI[where x="k+1"])
apply auto
using C(2) cons C(3) by blast
done
subgoal apply(rule pre_mono)
prefer 2 apply(simp) using C(3) conseq(1) apply fast
done
subgoal
apply(simp)
using C(4) conseq(1,3) apply blast done
apply(rule exI[where x="k*k2"]) apply(safe)
subgoal for l s
using C(5) cons apply(auto)
proof(goal_cases)
case 1
then have absch: "e s ≤ k2 * e' s" "time C s ≤ k * e s" by blast+
show ?case
using absch order_trans by fastforce
qed
done
qed
end
¤ Dauer der Verarbeitung: 0.27 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland
|
|