theory SepLogK_VCG
imports SepLogK_Hoare
begin
lemmas conseqS = conseq[where k=1, simplified]
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) |
Awhile assn2 bexp acom (‹({_}/ WHILE _/ DO _)› [0, 0, 61] 61)
notation com.SKIP (‹SKIP›)
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 ({_} WHILE b DO C) = (WHILE b DO strip C)"
fun pre :: "acom → assn2 → assn2" where
"pre SKIP Q = ($1 ** Q)" |
"pre (x ::= a) Q = ((λ(ps,t). x∈dom ps ∧ vars a ⊆ dom ps ∧ Q (ps(x↦(paval a ps)),t) ) ** $1)" |
"pre (C1;; C2) Q = pre C1 (pre C2 Q)" |
"pre (IF b THEN C1 ELSE C2) Q = (
$1 ** (λ(ps,n). vars b ⊆ dom ps ∧ (if pbval b ps then pre C1 Q (ps,n) else pre C2 Q (ps,n) )))" |
"pre ({I} WHILE b DO C) Q = (I ** $1)"
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 ({I} WHILE b DO C) Q = ( (∀s. (I s ⟶ vars b ⊆ dom (fst s) ) ∧ ((λ(s,n). I (s,n) ∧ lmaps_to_axpr b True s) s ⟶ pre C (I ** $ 1) s)
∧ ( (λ(s,n). I (s,n) ∧ lmaps_to_axpr b False s) s ⟶ Q s)) ∧ vc C (I ** $ 1))"
lemma dollar0_left: "($ 0 ∧* Q) = Q"
apply rule unfolding dollar_def sep_conj_def
by force
lemma vc_sound: "vc C Q ==> ⊨3' {pre C Q} strip C { Q }"
proof (induct C arbitrary: Q)
case Askip
then show ?case
apply simp
apply(rule conseqS[OF Frame[OF Skip]])
by (auto simp: dollar0_left)
next
case (Aassign x1 x2)
then show ?case
apply simp
apply(rule conseqS)
apply(rule Assign4)
apply auto done
next
case (Aseq C1 C2)
then show ?case apply (auto intro: Seq) done
next
case (Aif b C1 C2)
then have Aif1: "⊨3' {pre C1 Q} strip C1 {Q}"
and Aif2: "⊨3' {pre C2 Q} strip C2 {Q}" by auto
show ?case apply simp
apply (rule conseqS)
apply(rule If[where P="%(ps,n). (if pbval b ps then pre C1 Q (ps,n) else pre C2 Q (ps,n))" and Q="Q"])
subgoal apply simp
apply (rule conseqS) apply(fact Aif1) by auto
subgoal apply simp
apply (rule conseqS) apply(fact Aif2) by auto
apply (auto simp: sep_conj_ac)
unfolding sep_conj_def by blast
next
case (Awhile I b C)
then have
dom : "∧s. (I s ⟶ vars b ⊆ dom (fst s) )"
and i: "∧s. (λ(s,n). I (s,n) ∧ lmaps_to_axpr b True s) s ⟶ pre C (I ** $ 1) s"
and ii: "∧s. (λ(s,n). I (s,n) ∧ lmaps_to_axpr b False s) s ⟶ Q s"
and C: "⊨3' {pre C (I ** $ 1)} strip C {I ** $ 1}"
by fastforce+
show ?case
apply simp
apply(rule conseqS)
apply(rule While[where P=I])
apply(rule conseqS)
apply(rule C)
subgoal using i by auto
subgoal apply simp using dom unfolding sep_conj_def by force
subgoal apply simp using dom unfolding sep_conj_def by force
subgoal using ii apply auto done
done
qed
lemma vc2valid: "vc C Q ==> ∀s. P s ⟶ pre C Q s ==> ⊨3' {P} strip C { Q}"
using hoareT_sound2_part weakenpre vc_sound by metis
lemma pre_mono: assumes "∀s. P s ⟶ Q s" shows "∧s. pre C P s ==> pre C Q s"
using assms proof(induct C arbitrary: P Q)
case Askip
then show ?case apply (auto simp: sep_conj_def dollar_def)
by force
next
case (Aassign x1 x2)
then show ?case by (auto simp: sep_conj_def dollar_def)
next
case (Aseq C1 C2)
then show ?case by auto
next
case (Aif b C1 C2)
then show ?case apply (auto simp: sep_conj_def dollar_def)
subgoal for ps n
apply(rule exI[where x=0])
apply(rule exI[where x=1])
apply(rule exI[where x=ps]) by auto
done
next
case (Awhile x1 x2 C)
then show ?case by auto
qed
lemma vc_mono: assumes "∀s. P s ⟶ Q s" shows "vc C P ==> vc C Q"
using assms proof(induct C arbitrary: P Q)
case Askip
then show ?case by auto
next
case (Aassign x1 x2)
then show ?case by auto
next
case (Aseq C1 C2 P Q)
then have i: "vc C1 (pre C2 P)" and ii: "vc C2 P" by auto
from pre_mono[OF ] Aseq(4) have iii: "∀s. pre C2 P s ⟶ pre C2 Q s" by blast
show ?case apply auto
using Aseq(1)[OF i iii] Aseq(2)[OF ii Aseq(4)] by auto
next
case (Aif x1 C1 C2)
then show ?case by auto
next
case (Awhile I b C P Q)
then show ?case by auto
qed
lemma vc_sound': "vc C Q ==> (∧s n. P' (s, n) ==> pre C Q (s, k * n)) ==> (∧s n. Q (s, n) ==> Q' (s, n div k)) ==> 0 < k ==> ⊨3' {P'} strip C { Q'}"
using conseq vc_mono vc_sound by metis
lemma pre_Frame: "(∀s. P s ⟶ pre C Q s) ==> vc C Q
==> (∃C'. strip C = strip C' ∧ vc C' (Q ** F) ∧ (∀s. (P ** F) s ⟶ pre C' (Q ** F) s) )"
proof (induct C arbitrary: P Q)
case Askip
show ?case
proof (rule exI[where x="Askip"], safe)
fix a b
assume "(P ∧* F) (a, b)"
then obtain ps1 ps2 n1 n2 where A: "ps1##ps2" "a=ps1+ps2" "b=n1+n2"
and P: "P (ps1,n1)" and F: "F (ps2,n2)" unfolding sep_conj_def by auto
from P Askip have p: "($ (Suc 0) ∧* Q) (ps1, n1)" by auto
from p A F
have "(($ (Suc 0) ∧* Q) ∧* F) (a, b)"
apply(subst (2) sep_conj_def) by auto
then show "pre SKIP (Q ∧* F) (a, b)" by (simp add: sep_conj_ac)
qed simp
next
case (Aassign x a)
show ?case
proof (rule exI[where x="Aassign x a"], safe)
fix ps n
assume "(P ∧* F) (ps,n)"
then obtain ps1 ps2 n1 n2 where o: "ps1##ps2" "ps=ps1+ps2" "n=n1+n2"
and P: "P (ps1,n1)" and F: "F (ps2,n2)" unfolding sep_conj_def by auto
from P Aassign(1) have z: "((λ(ps, t). x ∈ dom ps ∧ vars a ⊆ dom ps ∧ Q (ps(x ↦ paval a ps), t))
∧* $ (Suc 0)) (ps1, n1)"
by auto
with o F show " pre (x ::= a) (Q ∧* F) (ps,n)" apply auto
unfolding sep_conj_def dollar_def apply (auto)
subgoal by(simp add: plus_fun_def)
subgoal by(auto simp add: plus_fun_def)
subgoal
by (smt add_update_distrib dom_fun_upd domain_conv insert_dom option.simps(3) paval_extend sep_disj_fun_def)
done
qed auto
next
case (Aseq C1 C2)
from Aseq(3) have pre: "∀s. P s ⟶ pre C1 (pre C2 Q) s" by auto
from Aseq(4) have vc1: "vc C1 (pre C2 Q)" and vc2: "vc C2 Q" by auto
from Aseq(1)[OF pre vc1] obtain C1' where S1: "strip C1 = strip C1'"
and vc1': "vc C1' (pre C2 Q ∧* F)"
and I1: "(∀s. (P ∧* F) s ⟶ pre C1' (pre C2 Q ∧* F) s)" by blast
from Aseq(2)[of "pre C2 Q" Q, OF _ vc2] obtain C2' where S2: "strip C2 = strip C2'"
and vc2': "vc C2' (Q ∧* F)"
and I2: "(∀s. (pre C2 Q ∧* F) s ⟶ pre C2' (Q ∧* F) s) " by blast
show ?case apply(rule exI[where x="Aseq C1' C2'"])
apply safe
subgoal using S1 S2 by auto
subgoal apply simp apply safe
subgoal using vc_mono[OF I2 vc1'] .
subgoal by (fact vc2')
done
subgoal using I1 I2 pre_mono
by force
done
next
case (Aif b C1 C2)
from Aif(3) have i: "∀s. P s ⟶
($ (Suc 0) ∧*
(λ(ps, n). vars b ⊆ dom ps ∧ (if pbval b ps then pre C1 Q (ps, n) else pre C2 Q (ps, n))))
s" by simp
from Aif(4) have vc1: "vc C1 Q" and vc2: "vc C2 Q" by auto
from Aif(1)[where P="pre C1 Q" and Q="Q", OF _ vc1] obtain C1' where
s1: "strip C1 = strip C1'" and v1: "vc C1' (Q ∧* F)"
and p1: "(∀s. (pre C1 Q ∧* F) s ⟶ pre C1' (Q ∧* F) s)"
by auto
from Aif(2)[where P="pre C2 Q" and Q="Q", OF _ vc2] obtain C2' where
s2: "strip C2 = strip C2'" and v2: "vc C2' (Q ∧* F)"
and p2: "(∀s. (pre C2 Q ∧* F) s ⟶ pre C2' (Q ∧* F) s)"
by auto
show ?case apply(rule exI[where x="Aif b C1' C2'"])
proof safe
fix ps n
assume "(P ∧* F) (ps, n)"
then obtain ps1 ps2 n1 n2 where o: "ps1##ps2" "ps=ps1+ps2" "n=n1+n2"
and P: "P (ps1,n1)" and F: "F (ps2,n2)" unfolding sep_conj_def by auto
from P i have P': "($ (Suc 0) ∧*
(λ(ps, n). vars b ⊆ dom ps ∧ (if pbval b ps then pre C1 Q (ps, n) else pre C2 Q (ps, n))))
(ps1,n1)" by auto
have PF: "(($ (Suc 0) ∧*
(λ(ps, n). vars b ⊆ dom ps ∧ (if pbval b ps then pre C1 Q (ps, n) else pre C2 Q (ps, n)))) ** F)
(ps,n)" apply(subst (2) sep_conj_def)
apply(rule exI[where x="(ps1,n1)"])
apply(rule exI[where x="(ps2,n2)"])
using F P' o by auto
from this[simplified sep_conj_assoc] obtain ps1 ps2 n1 n2 where o: "ps1##ps2" "ps=ps1+ps2" "n=n1+n2"
and P: "($ (Suc 0)) (ps1,n1)" and F: "((λ(ps, n). vars b ⊆ dom ps ∧ (if pbval b ps then pre C1 Q (ps, n) else pre C2 Q (ps, n))) ∧* F) (ps2,n2)"
unfolding sep_conj_def apply auto by fast
then have "((λ(ps, n). vars b ⊆ dom ps ∧ (if pbval b ps then (pre C1 Q ∧* F) (ps, n) else (pre C2 Q ∧* F) (ps, n)))) (ps2,n2)"
unfolding sep_conj_def apply auto
apply (metis contra_subsetD domD map_add_dom_app_simps(1) plus_fun_conv sep_add_commute)
using pbval_extend apply auto[1]
apply (metis contra_subsetD domD map_add_dom_app_simps(1) plus_fun_conv sep_add_commute)
using pbval_extend apply auto[1] done
then have "((λ(ps, n). vars b ⊆ dom ps ∧ (if pbval b ps then (pre C1' (Q ∧* F)) (ps, n) else (pre C2' (Q ∧* F)) (ps, n)))) (ps2,n2)"
using p1 p2 by auto
with o P
show "pre (IF b THEN C1' ELSE C2') (Q ∧* F) (ps, n)"
apply auto apply(subst sep_conj_def) by force
qed (auto simp: s1 s2 v1 v2)
next
case (Awhile I b C)
from Awhile(2) have pre: "∀s. P s ⟶ (I ** $1) s" by auto
from Awhile(3) have
dom: "∀ps n. I (ps, n) ⟶ vars b ⊆ dom ps"
and tB: "∀s. I s ∧ vars b ⊆ dom (fst s) ∧ pbval b (fst s) ⟶ pre C (I ∧* $ (Suc 0)) s"
and fB: "∀ps n. I (ps, n) ∧ vars b ⊆ dom ps ∧ ¬ pbval b ps ⟶ Q (ps, n)"
and vcB: "vc C (I ∧* $(Suc 0))" by auto
from Awhile(1)[OF tB vcB] obtain C' where st: "strip C = strip C'"
and vc': "vc C' ((I ∧* $ (Suc 0)) ∧* F)"
and pre': "(∀s. ((λa. I a ∧ vars b ⊆ dom (fst a) ∧ pbval b (fst a)) ∧* F) s ⟶
pre C' ((I ∧* $ (Suc 0)) ∧* F) s)"
by auto
show ?case apply(rule exI[where x="Awhile (I**F) b C'"])
apply safe
subgoal using st by simp
subgoal apply simp apply safe
subgoal using dom unfolding sep_conj_def apply auto
by (metis domD sep_substate_disj_add subState subsetCE)
subgoal using pre' apply(auto simp: sep_conj_ac)
apply(subst (asm) sep_conj_def)
apply(subst (asm) sep_conj_def) apply auto
by (metis dom pbval_extend sep_add_commute sep_disj_commuteI)
subgoal using fB unfolding sep_conj_def apply auto
using dom pbval_extend by fastforce
subgoal using vc' apply(auto simp: sep_conj_ac) done
done
subgoal apply simp using pre unfolding sep_conj_def apply auto
by (smt semiring_normalization_rules(23) sep_add_assoc sep_add_commute sep_add_disjD sep_add_disjI1)
done
qed
lemma vc_complete: "⊨3a {P} c { Q } ==> (∃C. vc C Q ∧ (∀s. P s ⟶ pre C Q s) ∧ strip C = c)"
proof(induct rule: hoare3a.induct)
case Skip
then show ?case apply(rule exI[where x="Askip"]) by auto
next
case (Assign4 x a Q)
then show ?case apply(rule exI[where x="Aassign x a"]) by auto
next
case (If P b c1 Q c2)
from If(2) obtain C1 where A1: "vc C1 Q" "strip C1 = c1" and
A2: "∧ps n. (P (ps, n) ∧ lmaps_to_axpr b True ps) ⟶ pre C1 Q (ps,n)"
by blast
from If(4) obtain C2 where B1: "vc C2 Q" "strip C2 = c2" and B2:
"∧ps n. (P (ps, n) ∧ lmaps_to_axpr b False ps) ⟶ pre C2 Q (ps,n)"
by blast
show ?case apply(rule exI[where x="Aif b C1 C2"]) using A1 B1 apply auto
subgoal for ps n
unfolding sep_conj_def dollar_def apply auto
apply(rule exI[where x="0"])
apply(rule exI[where x="1"])
apply(rule exI[where x="ps"])
using A2 B2 by auto
done
next
case (Frame P C Q F)
then obtain C' where vc: "vc C' Q" and pre: "(∀s. P s ⟶ pre C' Q s)"
and strip: "strip C' = C" by auto
show ?case using pre_Frame[OF pre vc] strip by metis
next
case (Seq P c1 Q c2 R)
from Seq(2) obtain C1 where A1: "vc C1 Q" "strip C1 = c1" and
A2: "∧s. P s ⟶ pre C1 Q s"
by blast
from Seq(4) obtain C2 where B1: "vc C2 R" "strip C2 = c2" and
B2: "∧s. Q s ⟶ pre C2 R s"
by blast
show ?case apply(rule exI[where x="Aseq C1 C2"])
using B1 A1 apply auto
subgoal using vc_mono B2 by auto
subgoal apply(rule pre_mono[where P=Q]) using B2 apply auto
using A2 by auto
done
next
case (While I b c)
then obtain C where 1: "vc C ((λ(s, n). I (s, n) ∧ vars b ⊆ dom s) ∧* $ 1)"
"strip C = c" and 2:
"∧ps n. (I (ps, n) ∧ lmaps_to_axpr b True ps) ⟶
pre C ((λ(s, n). I (s, n) ∧ vars b ⊆ dom s) ∧* $ 1) (ps,n) " by blast
show ?case apply(rule exI[where x="Awhile (λ(s, n). I (s, n) ∧ vars b ⊆ dom s) b C"])
using 1 2 by auto
next
case (conseqS P c Q P' Q')
then obtain C' where C': "vc C' Q" "(∀s. P s ⟶ pre C' Q s)" "strip C' = c"
by blast
show ?case apply(rule exI[where x=C'])
using C' conseqS(3,4) pre_mono vc_mono by force
qed
theorem vc_completeness:
assumes "⊨3' {P} c { Q}"
shows "∃C k. vc C (Q ** sep_true)
∧ (∀ps n. P (ps, n) ⟶ pre C (λ(ps, n). (Q ** sep_true) (ps, n div k)) (ps, k * n))
∧ strip C = c"
proof -
let ?QG = "λk (ps,n). (Q ** sep_true) (ps,n div k)"
from assms obtain k where k[simp]: "k>0" and p: "∧ps n. P (ps, n) ==> wp3' c (λ(ps, n). (Q ** sep_true) (ps, n div k)) (ps, k * n)"
using valid_wp by blast
from wpT_is_pre have R: "⊨3a {wp3' c (?QG k)} c {?QG k}" by auto
have z: "(∀s. (λ(ps, n). (Q ∧* (λs. True)) (ps, n div k)) s) ==> (∀s. (λ(ps, n). (Q ∧* (λs. True)) (ps, n)) s)"
by (metis (no_types) case_prod_conv k neq0_conv nonzero_mult_div_cancel_left old.prod.exhaust)
have z: "∧ps n. ((Q ∧* (λs. True)) (ps, n div k) ==> (Q ∧* (λs. True)) (ps, n))"
proof -
fix ps n
assume "(Q ∧* (λs. True)) (ps, n div k) "
then obtain ps1 n1 ps2 n2
where o: "ps1 ## ps2" "ps = ps1 + ps2" "Q (ps1, n1)" "n div k = n1 + n2"
unfolding sep_conj_def by auto
from o(4) have nn1: "n≥n1" using k
by (metis (full_types) add_leE div_le_dividend)
show "(Q ∧* (λs. True)) (ps, n)" unfolding sep_conj_def
apply(rule exI[where x="(ps1, n1)"])
apply(rule exI[where x="(ps2, n - n1)"])
using o nn1 by auto
qed
then have z': "∀s. ((Q ∧* (λs. True)) (fst s, (snd s) div k) ⟶ (Q ∧* (λs. True)) s)"
by (metis prod.collapse)
from vc_complete[OF R] obtain C
where o: "vc C (λ(ps, n). (Q ∧* (λs. True)) (ps, n div k))"
"∀a b. wp3' (strip C) (λ(ps, n). (Q ∧* (λs. True)) (ps, n div k)) (a, b) ⟶
pre C (λ(ps, n). (Q ∧* (λs. True)) (ps, n div k)) (a, b)"
"c = strip C" by auto
have y: "∧ps n. P (ps, n) ==> pre C (λ(ps, n). (Q ∧* (λs. True)) (ps, n div k)) (ps, k * n)"
using o p by metis
show ?thesis apply(rule exI[where x=C]) apply(rule exI[where x=k])
apply safe
subgoal apply(rule vc_mono[OF _ o(1)]) using z by blast
subgoal using y by blast
subgoal using o by simp
done
qed
end
¤ Dauer der Verarbeitung: 0.4 Sekunden
(vorverarbeitet am 2026-11-04)
¤
*© Formatika GbR, Deutschland
|
|