Theory Logic
section ‹Hyper Hoare Logic›
text ‹This file contains technical results from sections 3 and 5:
- Hyper-assertions (definition 3)
- Hyper-triples (definition 5)
- Core rules of Hyper Hoare Logic (figure 2)
- Soundness of the core rules (theorem 1)
- Completeness of the core rules (theorem 2)
- Ability to disprove hyper-triples (theorem 5)›
theory Logic
imports Language
begin
text ‹Definition 3›
type_synonym 'a hyperassertion = "('a set ⇒ bool)"
definition entails where
"entails A B ⟷ (∀S. A S ⟶ B S)"
lemma entails_refl:
"entails A A"
by (simp add: entails_def)
lemma entailsI:
assumes "⋀S. A S ⟹ B S"
shows "entails A B"
by (simp add: assms entails_def)
lemma entailsE:
assumes "entails A B"
and "A x"
shows "B x"
by (meson assms(1) assms(2) entails_def)
lemma bientails_equal:
assumes "entails A B"
and "entails B A"
shows "A = B"
proof (rule ext)
fix S show "A S = B S"
by (meson assms(1) assms(2) entailsE)
qed
lemma entails_trans:
assumes "entails A B"
and "entails B C"
shows "entails A C"
by (metis assms(1) assms(2) entails_def)
definition setify_prop where
"setify_prop b = { (l, σ) |l σ. b σ}"
lemma sem_assume_setify:
"sem (Assume b) S = S ∩ setify_prop b" (is "?A = ?B")
proof -
have "⋀l σ. (l, σ) ∈ ?A ⟷ (l, σ) ∈ ?B"
proof -
fix l σ
have "(l, σ) ∈ ?A ⟷ (l, σ) ∈ S ∧ b σ"
by (simp add: assume_sem)
then show "(l, σ) ∈ ?A ⟷ (l, σ) ∈ ?B"
by (simp add: setify_prop_def)
qed
then show ?thesis
by auto
qed
definition over_approx :: "'a set ⇒ 'a hyperassertion" where
"over_approx P S ⟷ S ⊆ P"
definition lower_closed :: "'a hyperassertion ⇒ bool" where
"lower_closed P ⟷ (∀S S'. P S ∧ S' ⊆ S ⟶ P S')"
lemma over_approx_lower_closed:
"lower_closed (over_approx P)"
by (metis (full_types) lower_closed_def order_trans over_approx_def)
definition under_approx :: "'a set ⇒ 'a hyperassertion" where
"under_approx P S ⟷ P ⊆ S"
definition upper_closed :: "'a hyperassertion ⇒ bool" where
"upper_closed P ⟷ (∀S S'. P S ∧ S ⊆ S' ⟶ P S')"
lemma under_approx_upper_closed:
"upper_closed (under_approx P)"
by (metis (no_types, lifting) order.trans under_approx_def upper_closed_def)
definition closed_by_union :: "'a hyperassertion ⇒ bool" where
"closed_by_union P ⟷ (∀S S'. P S ∧ P S' ⟶ P (S ∪ S'))"
lemma closed_by_unionI:
assumes "⋀a b. P a ⟹ P b ⟹ P (a ∪ b)"
shows "closed_by_union P"
by (simp add: assms closed_by_union_def)
lemma closed_by_union_over:
"closed_by_union (over_approx P)"
by (simp add: closed_by_union_def over_approx_def)
lemma closed_by_union_under:
"closed_by_union (under_approx P)"
by (simp add: closed_by_union_def sup.coboundedI1 under_approx_def)
definition conj where
"conj P Q S ⟷ P S ∧ Q S"
lemma entail_conj:
assumes "entails A B"
shows "entails A (conj A B)"
by (metis (full_types) assms conj_def entails_def)
lemma entail_conj_weaken:
"entails (conj A B) A"
by (simp add: conj_def entails_def)
definition disj where
"disj P Q S ⟷ P S ∨ Q S"
definition exists :: "('c ⇒ 'a hyperassertion) ⇒ 'a hyperassertion" where
"exists P S ⟷ (∃x. P x S)"
definition forall :: "('c ⇒ 'a hyperassertion) ⇒ 'a hyperassertion" where
"forall P S ⟷ (∀x. P x S)"
lemma over_inter:
"entails (over_approx (P ∩ Q)) (conj (over_approx P) (over_approx Q))"
by (simp add: conj_def entails_def over_approx_def)
lemma over_union:
"entails (disj (over_approx P) (over_approx Q)) (over_approx (P ∪ Q))"
by (metis disj_def entailsI le_supI1 le_supI2 over_approx_def)
lemma under_union:
"entails (under_approx (P ∪ Q)) (disj (under_approx P) (under_approx Q))"
by (simp add: disj_def entails_def under_approx_def)
lemma under_inter:
"entails (conj (under_approx P) (under_approx Q)) (under_approx (P ∩ Q))"
by (simp add: conj_def entails_def le_infI1 under_approx_def)
text ‹Definition 6: Operator ‹⊗››
definition join :: "'a hyperassertion ⇒ 'a hyperassertion ⇒ 'a hyperassertion" where
"join A B S ⟷ (∃SA SB. A SA ∧ B SB ∧ S = SA ∪ SB)"
definition general_join :: "('b ⇒ 'a hyperassertion) ⇒ 'a hyperassertion" where
"general_join f S ⟷ (∃F. S = (⋃x. F x) ∧ (∀x. f x (F x)))"
lemma general_joinI:
assumes "S = (⋃x. F x)"
and "⋀x. f x (F x)"
shows "general_join f S"
using assms(1) assms(2) general_join_def by blast
lemma join_closed_by_union:
assumes "closed_by_union Q"
shows "join Q Q = Q"
proof
fix S
show "join Q Q S ⟷ Q S"
by (metis assms closed_by_union_def join_def sup_idem)
qed
lemma entails_join_entails:
assumes "entails A1 B1"
and "entails A2 B2"
shows "entails (join A1 A2) (join B1 B2)"
proof (rule entailsI)
fix S assume "join A1 A2 S"
then obtain S1 S2 where "A1 S1" "A2 S2" "S = S1 ∪ S2"
by (metis join_def)
then show "join B1 B2 S"
by (metis assms(1) assms(2) entailsE join_def)
qed
text ‹Definition 7: Operator ‹⨂› (for ‹x ∈ X›)›
definition natural_partition where
"natural_partition I S ⟷ (∃F. S = (⋃n. F n) ∧ (∀n. I n (F n)))"
lemma natural_partitionI:
assumes "S = (⋃n. F n)"
and "⋀n. I n (F n)"
shows "natural_partition I S"
using assms(1) assms(2) natural_partition_def by blast
lemma natural_partitionE:
assumes "natural_partition I S"
obtains F where "S = (⋃n. F n)" "⋀n. I n (F n)"
by (meson assms natural_partition_def)
subsection ‹Rules of the Logic›
text ‹Core rules from figure 2›
inductive syntactic_HHT ::
"(('lvar, 'lval, 'pvar, 'pval) state hyperassertion) ⇒ ('pvar, 'pval) stmt ⇒ (('lvar, 'lval, 'pvar, 'pval) state hyperassertion) ⇒ bool"
(‹⊢ {_} _ {_}› [51,0,0] 81) where
RuleSkip: "⊢ {P} Skip {P}"
| RuleCons: "⟦ entails P P' ; entails Q' Q ; ⊢ {P'} C {Q'} ⟧ ⟹ ⊢ {P} C {Q}"
| RuleSeq: "⟦ ⊢ {P} C1 {R} ; ⊢ {R} C2 {Q} ⟧ ⟹ ⊢ {P} (Seq C1 C2) {Q}"
| RuleIf: "⟦ ⊢ {P} C1 {Q1} ; ⊢ {P} C2 {Q2} ⟧ ⟹ ⊢ {P} (If C1 C2) {join Q1 Q2}"
| RuleWhile: "⟦ ⋀n. ⊢ {I n} C {I (Suc n)} ⟧ ⟹ ⊢ {I 0} (While C) {natural_partition I}"
| RuleAssume: "⊢ { (λS. P (Set.filter (b ∘ snd) S)) } (Assume b) {P}"
| RuleAssign: "⊢ { (λS. P { (l, σ(x := e σ)) |l σ. (l, σ) ∈ S }) } (Assign x e) {P}"
| RuleHavoc: "⊢ { (λS. P { (l, σ(x := v)) |l σ v. (l, σ) ∈ S }) } (Havoc x) {P}"
| RuleExistsSet: "⟦⋀x::('lvar, 'lval, 'pvar, 'pval) state set. ⊢ {P x} C {Q x}⟧ ⟹ ⊢ {exists P} C {exists Q}"
subsection ‹Soundness›
text ‹Definition 5: Hyper-Triples›
definition hyper_hoare_triple (‹⊨ {_} _ {_}› [51,0,0] 81) where
"⊨ {P} C {Q} ⟷ (∀S. P S ⟶ Q (sem C S))"
lemma hyper_hoare_tripleI:
assumes "⋀S. P S ⟹ Q (sem C S)"
shows "⊨ {P} C {Q}"
by (simp add: assms hyper_hoare_triple_def)
lemma hyper_hoare_tripleE:
assumes "⊨ {P} C {Q}"
and "P S"
shows "Q (sem C S)"
using assms(1) assms(2) hyper_hoare_triple_def
by metis
lemma consequence_rule:
assumes "entails P P'"
and "entails Q' Q"
and "⊨ {P'} C {Q'}"
shows "⊨ {P} C {Q}"
by (metis (no_types, opaque_lifting) assms(1) assms(2) assms(3) entails_def hyper_hoare_triple_def)
lemma skip_rule:
"⊨ {P} Skip {P}"
by (simp add: hyper_hoare_triple_def sem_skip)
lemma assume_rule:
"⊨ { (λS. P (Set.filter (b ∘ snd) S)) } (Assume b) {P}"
proof (rule hyper_hoare_tripleI)
fix S assume "P (Set.filter (b ∘ snd) S)"
then show "P (sem (Assume b) S)"
by (simp add: assume_sem)
qed
lemma seq_rule:
assumes "⊨ {P} C1 {R}"
and "⊨ {R} C2 {Q}"
shows "⊨ {P} Seq C1 C2 {Q}"
using assms(1) assms(2) hyper_hoare_triple_def sem_seq
by metis
lemma if_rule:
assumes "⊨ {P} C1 {Q1}"
and "⊨ {P} C2 {Q2}"
shows "⊨ {P} If C1 C2 {join Q1 Q2}"
by (metis (full_types) assms(1) assms(2) hyper_hoare_triple_def join_def sem_if)
lemma sem_assign:
"sem (Assign x e) S = {(l, σ(x := e σ)) |l σ. (l, σ) ∈ S}" (is "?A = ?B")
proof
show "?A ⊆ ?B"
proof (rule subsetPairI)
fix l σ'
assume "(l, σ') ∈ sem (Assign x e) S"
then obtain σ where "(l, σ) ∈ S" "single_sem (Assign x e) σ σ'"
by (metis fst_eqD in_sem snd_conv)
then show "(l, σ') ∈ {(l, σ(x := e σ)) |l σ. (l, σ) ∈ S}"
by blast
qed
show "?B ⊆ ?A"
proof (rule subsetPairI)
fix l σ'
assume "(l, σ') ∈ ?B"
then obtain σ where "σ' = σ(x := e σ)" "(l, σ) ∈ S"
by blast
then show "(l, σ') ∈ ?A"
by (metis SemAssign fst_eqD in_sem snd_conv)
qed
qed
lemma assign_rule:
"⊨ { (λS. P { (l, σ(x := e σ)) |l σ. (l, σ) ∈ S }) } (Assign x e) {P}"
proof (rule hyper_hoare_tripleI)
fix S assume "P {(l, σ(x := e σ)) |l σ. (l, σ) ∈ S}"
then show "P (sem (Assign x e) S)" using sem_assign
by metis
qed
lemma sem_havoc:
"sem (Havoc x) S = {(l, σ(x := v)) |l σ v. (l, σ) ∈ S}" (is "?A = ?B")
proof
show "?A ⊆ ?B"
proof (rule subsetPairI)
fix l σ'
assume "(l, σ') ∈ sem (Havoc x) S"
then obtain σ where "(l, σ) ∈ S" "single_sem (Havoc x) σ σ'"
by (metis fst_eqD in_sem snd_conv)
then show "(l, σ') ∈ {(l, σ(x := v)) |l σ v. (l, σ) ∈ S}"
by blast
qed
show "?B ⊆ ?A"
proof (rule subsetPairI)
fix l σ'
assume "(l, σ') ∈ ?B"
then obtain σ v where "σ' = σ(x := v)" "(l, σ) ∈ S"
by blast
then show "(l, σ') ∈ ?A"
by (metis SemHavoc fst_eqD in_sem snd_conv)
qed
qed
lemma havoc_rule:
"⊨ { (λS. P { (l, σ(x := v)) |l σ v. (l, σ) ∈ S }) } (Havoc x) {P}"
proof (rule hyper_hoare_tripleI)
fix S assume "P { (l, σ(x := v)) |l σ v. (l, σ) ∈ S }"
then show "P (sem (Havoc x) S)" using sem_havoc by metis
qed
text ‹Loops›
lemma indexed_invariant_then_power:
assumes "⋀n. hyper_hoare_triple (I n) C (I (Suc n))"
and "I 0 S"
shows "I n (iterate_sem n C S)"
using assms
proof (induct n arbitrary: S)
next
case (Suc n)
then have "I n (iterate_sem n C S)"
by blast
then have "I (Suc n) (sem C (iterate_sem n C S))"
using Suc.prems(1) hyper_hoare_tripleE by blast
then show ?case
by (simp add: Suc.hyps Suc.prems(1))
qed (auto)
lemma indexed_invariant_then_power_bounded:
assumes "⋀m. m < n ⟹ hyper_hoare_triple (I m) C (I (Suc m))"
and "I 0 S"
shows "I n (iterate_sem n C S)"
using assms
proof (induct n arbitrary: S)
next
case (Suc n)
then have "I n (iterate_sem n C S)"
using less_Suc_eq by presburger
then have "I (Suc n) (sem C (iterate_sem n C S))"
using Suc.prems(1) hyper_hoare_tripleE by blast
then show ?case
by (simp add: Suc.hyps Suc.prems(1))
qed (auto)
lemma while_rule:
assumes "⋀n. hyper_hoare_triple (I n) C (I (Suc n))"
shows "hyper_hoare_triple (I 0) (While C) (natural_partition I)"
proof (rule hyper_hoare_tripleI)
fix S assume asm0: "I 0 S"
show "natural_partition I (sem (While C) S)"
proof (rule natural_partitionI)
show "sem (While C) S = ⋃ (range (λn. iterate_sem n C S))"
by (simp add: sem_while)
fix n show "I n (iterate_sem n C S)"
by (simp add: asm0 assms indexed_invariant_then_power)
qed
qed
lemma rule_exists:
assumes "⋀x. ⊨ {P x} C {Q x}"
shows "⊨ {exists P} C {exists Q}"
by (metis assms exists_def hyper_hoare_triple_def)
text ‹Theorem 1›
theorem soundness:
assumes "⊢ {A} C {B}"
shows "⊨ {A} C {B}"
using assms
proof (induct rule: syntactic_HHT.induct)
case (RuleSkip P)
then show ?case
using skip_rule by auto
next
case (RuleCons P P' Q' Q C)
then show ?case
using consequence_rule by blast
next
case (RuleExistsSet P C Q)
then show ?case
using rule_exists by blast
next
case (RuleSeq P C1 R C2 Q)
then show ?case
using seq_rule by meson
next
case (RuleIf P C1 Q1 C2 Q2)
then show ?case
using if_rule by blast
next
case (RuleAssume P b)
then show ?case
by (simp add: assume_rule)
next
case (RuleWhile I C)
then show ?case
using while_rule by blast
next
case (RuleAssign x e)
then show ?case
by (simp add: assign_rule)
next
case (RuleHavoc x)
then show ?case
using havoc_rule by fastforce
qed
subsection ‹Completeness›
definition complete
where
"complete P C Q ⟷ (⊨ {P} C {Q} ⟶ ⊢ {P} C {Q})"
lemma completeI:
assumes "⊨ {P} C {Q} ⟹ ⊢ {P} C {Q}"
shows "complete P C Q"
by (simp add: assms complete_def)
lemma completeE:
assumes "complete P C Q"
and "⊨ {P} C {Q}"
shows "⊢ {P} C {Q}"
using assms complete_def by auto
lemma complete_if_aux:
assumes "hyper_hoare_triple A (If C1 C2) B"
shows "entails (λS'. ∃S. A S ∧ S' = sem C1 S ∪ sem C2 S) B"
proof (rule entailsI)
fix S' assume "∃S. A S ∧ S' = sem C1 S ∪ sem C2 S"
then show "B S'"
by (metis assms hyper_hoare_tripleE sem_if)
qed
lemma complete_if:
fixes P Q :: "('lvar, 'lval, 'pvar, 'pval) state hyperassertion"
assumes "⋀P1 Q1 :: ('lvar, 'lval, 'pvar, 'pval) state hyperassertion. complete P1 C1 Q1"
and "⋀P2 Q2 :: ('lvar, 'lval, 'pvar, 'pval) state hyperassertion. complete P2 C2 Q2"
shows "complete P (If C1 C2) Q"
proof (rule completeI)
assume asm0: "⊨ {P} If C1 C2 {Q}"
show "⊢ {P} stmt.If C1 C2 {Q}"
proof (rule RuleCons)
show "⊢ {exists (λV S. P S ∧ S = V)} stmt.If C1 C2 {exists (λV. join (λS. S = sem C1 V ∧ P V) (λS. S = sem C2 V))}"
proof (rule RuleExistsSet)
fix V
show "⊢ {(λS. P S ∧ S = V)} stmt.If C1 C2 {join (λS. S = sem C1 V ∧ P V) (λS. S = sem C2 V)}"
proof (rule RuleIf)
show "⊢ {(λS. P S ∧ S = V)} C1 {λS. S = sem C1 V ∧ P V}"
by (simp add: assms(1) completeE hyper_hoare_triple_def)
show "⊢ {(λS. P S ∧ S = V)} C2 {λS. S = sem C2 V}"
by (simp add: assms(2) completeE hyper_hoare_triple_def)
qed
qed
show "entails P (exists (λV S. P S ∧ S = V))"
by (simp add: entailsI exists_def)
show "entails (exists (λV. join (λS. S = sem C1 V ∧ P V) (λS. S = sem C2 V))) Q"
proof (rule entailsI)
fix S assume "exists (λV. join (λS. S = sem C1 V ∧ P V) (λS. S = sem C2 V)) S"
then obtain V where "join (λS. S = sem C1 V ∧ P V) (λS. S = sem C2 V) S"
by (meson exists_def)
then obtain S1 S2 where "S = S1 ∪ S2" "S1 = sem C1 V ∧ P V" "S2 = sem C2 V"
by (simp add: join_def)
then show "Q S"
by (metis asm0 hyper_hoare_tripleE sem_if)
qed
qed
qed
lemma complete_seq_aux:
assumes "hyper_hoare_triple A (Seq C1 C2) B"
shows "∃R. hyper_hoare_triple A C1 R ∧ hyper_hoare_triple R C2 B"
proof -
let ?R = "λS. ∃S'. A S' ∧ S = sem C1 S'"
have "hyper_hoare_triple A C1 ?R"
using hyper_hoare_triple_def by blast
moreover have "hyper_hoare_triple ?R C2 B"
proof (rule hyper_hoare_tripleI)
fix S assume "∃S'. A S' ∧ S = sem C1 S'"
then obtain S' where asm0: "A S'" "S = sem C1 S'"
by blast
then show "B (sem C2 S)"
by (metis assms hyper_hoare_tripleE sem_seq)
qed
ultimately show ?thesis by blast
qed
lemma complete_assume:
"complete P (Assume b) Q"
proof (rule completeI)
assume asm0: "⊨ {P} Assume b {Q}"
show "⊢ {P} Assume b {Q}"
proof (rule RuleCons)
show "⊢ { (λS. Q (Set.filter (b ∘ snd) S)) } (Assume b) {Q}"
by (simp add: RuleAssume)
show "entails P (λS. Q (Set.filter (b ∘ snd) S))"
by (metis (mono_tags, lifting) asm0 assume_sem entails_def hyper_hoare_tripleE)
show "entails Q Q"
by (simp add: entailsI)
qed
qed
lemma complete_skip:
"complete P Skip Q"
using completeI RuleSkip
by (metis (mono_tags, lifting) entails_def hyper_hoare_triple_def sem_skip RuleCons)
lemma complete_assign:
"complete P (Assign x e) Q"
proof (rule completeI)
assume asm0: "⊨ {P} Assign x e {Q}"
show "⊢ {P} Assign x e {Q}"
proof (rule RuleCons)
show "⊢ {(λS. Q {(l, σ(x := e σ)) |l σ. (l, σ) ∈ S})} Assign x e {Q}"
by (simp add: RuleAssign)
show "entails P (λS. Q {(l, σ(x := e σ)) |l σ. (l, σ) ∈ S})"
proof (rule entailsI)
fix S assume "P S"
then show "Q {(l, σ(x := e σ)) |l σ. (l, σ) ∈ S}"
by (metis asm0 hyper_hoare_triple_def sem_assign)
qed
show "entails Q Q"
by (simp add: entailsI)
qed
qed
lemma complete_havoc:
"complete P (Havoc x) Q"
proof (rule completeI)
assume asm0: "⊨ {P} Havoc x {Q}"
show "⊢ {P} Havoc x {Q}"
proof (rule RuleCons)
show "⊢ { (λS. Q { (l, σ(x := v)) |l σ v. (l, σ) ∈ S }) } (Havoc x) {Q}"
using RuleHavoc by fast
show "entails P (λS. Q {(l, σ(x := v)) |l σ v. (l, σ) ∈ S})"
proof (rule entailsI)
fix S assume "P S"
then show "Q {(l, σ(x := v)) |l σ v. (l, σ) ∈ S}"
by (metis asm0 hyper_hoare_triple_def sem_havoc)
qed
show "entails Q Q"
by (simp add: entailsI)
qed
qed
lemma complete_seq:
assumes "⋀R. complete P C1 R"
and "⋀R. complete R C2 Q"
shows "complete P (Seq C1 C2) Q"
by (meson RuleSeq assms(1) assms(2) completeE completeI complete_seq_aux)
fun construct_inv
where
"construct_inv P C 0 = P"
| "construct_inv P C (Suc n) = (λS. (∃S'. S = sem C S' ∧ construct_inv P C n S'))"
lemma iterate_sem_ind:
assumes "construct_inv P C n S'"
shows "∃S. P S ∧ S' = iterate_sem n C S"
using assms
by (induct n arbitrary: S') (auto)
lemma complete_while_aux:
assumes "hyper_hoare_triple (λS. P S ∧ S = V) (While C) Q"
shows "entails (natural_partition (construct_inv (λS. P S ∧ S = V) C)) Q"
proof (rule entailsI)
fix S assume "natural_partition (construct_inv (λS. P S ∧ S = V) C) S"
then obtain F where asm0: "S = (⋃n. F n)" "⋀n. construct_inv (λS. P S ∧ S = V) C n (F n)"
using natural_partitionE by blast
then have "P (F 0) ∧ F 0 = V"
by (metis (mono_tags, lifting) construct_inv.simps(1))
then have "Q (⋃n. iterate_sem n C (F 0))"
using assms hyper_hoare_triple_def[of "λS. P S ∧ S = V" "While C" Q] sem_while
by metis
moreover have "⋀n. F n = iterate_sem n C V"
proof -
fix n
obtain S' where "P S' ∧ S' = V" "F n = iterate_sem n C S'"
using asm0(2) iterate_sem_ind by blast
then show "F n = iterate_sem n C V"
by simp
qed
ultimately show "Q S"
using asm0(1) by auto
qed
lemma complete_while:
fixes P Q :: "('lvar, 'lval, 'pvar, 'pval) state hyperassertion"
assumes "⋀P' Q' :: ('lvar, 'lval, 'pvar, 'pval) state hyperassertion. complete P' C Q'"
shows "complete P (While C) Q"
proof (rule completeI)
assume asm0: "hyper_hoare_triple P (While C) Q"
let ?I = "λV. construct_inv (λS. P S ∧ S = V) C"
have r: "⋀V. syntactic_HHT (?I V 0) (While C) (natural_partition (?I V))"
proof (rule RuleWhile)
fix V n show "syntactic_HHT (construct_inv (λS. P S ∧ S = V) C n) C (construct_inv (λS. P S ∧ S = V) C (Suc n))"
by (meson assms completeE construct_inv.simps(2) hyper_hoare_tripleI)
qed
show "syntactic_HHT P (While C) Q"
proof (rule RuleCons)
show "syntactic_HHT (exists (λV. ?I V 0)) (While C) (exists (λV. ((natural_partition (?I V)))))"
using r by (rule RuleExistsSet)
show "entails P (exists (λV. construct_inv (λS. P S ∧ S = V) C 0))"
by (simp add: entailsI exists_def)
show "entails (exists (λV. natural_partition (construct_inv (λS. P S ∧ S = V) C))) Q"
proof (rule entailsI)
fix S' assume "exists (λV. natural_partition (construct_inv (λS. P S ∧ S = V) C)) S'"
then obtain V where "natural_partition (construct_inv (λS. P S ∧ S = V) C) S'"
by (meson exists_def)
moreover have "entails (natural_partition (construct_inv (λS. P S ∧ S = V) C)) Q"
proof (rule complete_while_aux)
show "hyper_hoare_triple (λS. P S ∧ S = V) (While C) Q"
using asm0 hyper_hoare_triple_def[of "λS. P S ∧ S = V"]
hyper_hoare_triple_def[of P "While C" Q] by auto
qed
ultimately show "Q S'"
by (simp add: entails_def)
qed
qed
qed
text ‹Theorem 2›
theorem completeness:
fixes P Q :: "('lvar, 'lval, 'pvar, 'pval) state hyperassertion"
assumes "⊨ {P} C {Q}"
shows "⊢ {P} C {Q}"
using assms
proof (induct C arbitrary: P Q)
case (Assign x1 x2)
then show ?case
using completeE complete_assign by fast
next
case (Seq C1 C2)
then show ?case
using complete_def complete_seq by meson
next
case (If C1 C2)
then show ?case
using complete_def complete_if by meson
next
case Skip
then show ?case
using complete_def complete_skip by meson
next
case (Havoc x)
then show ?case
by (simp add: completeE complete_havoc)
next
case (Assume b)
then show ?case
by (simp add: completeE complete_assume)
next
case (While C)
then show ?case
using complete_def complete_while by blast
qed
subsection ‹Disproving Hyper-Triples›
definition sat where "sat P ⟷ (∃S. P S)"
text ‹Theorem 5›
theorem disproving_triple:
"¬ ⊨ {P} C {Q} ⟷ (∃P'. sat P' ∧ entails P' P ∧ ⊨ {P'} C {λS. ¬ Q S})" (is "?A ⟷ ?B")
proof
assume "¬ ⊨ {P} C {Q}"
then obtain S where asm0: "P S" "¬ Q (sem C S)"
using hyper_hoare_triple_def by blast
let ?P = "λS'. S = S'"
have "entails ?P P"
by (simp add: asm0(1) entails_def)
moreover have "⊨ {?P} C {λS. ¬ Q S}"
by (simp add: asm0(2) hyper_hoare_triple_def)
moreover have "sat ?P"
by (simp add: sat_def)
ultimately show ?B by blast
next
assume "∃P'. sat P' ∧ entails P' P ∧ ⊨ {P'} C {λS. ¬ Q S}"
then obtain P' where asm0: "sat P'" "entails P' P" "⊨ {P'} C {λS. ¬ Q S}"
by blast
then obtain S where "P' S"
by (meson sat_def)
then show ?A
using asm0(2) asm0(3) entailsE hyper_hoare_tripleE
by (metis (no_types, lifting))
qed
definition differ_only_by where
"differ_only_by a b x ⟷ (∀y. y ≠ x ⟶ a y = b y)"
lemma differ_only_byI:
assumes "⋀y. y ≠ x ⟹ a y = b y"
shows "differ_only_by a b x"
by (simp add: assms differ_only_by_def)
lemma diff_by_update:
"differ_only_by (a(x := v)) a x"
by (simp add: differ_only_by_def)
lemma diff_by_comm:
"differ_only_by a b x ⟷ differ_only_by b a x"
by (metis (mono_tags, lifting) differ_only_by_def)
lemma diff_by_trans:
assumes "differ_only_by a b x"
and "differ_only_by b c x"
shows "differ_only_by a c x"
by (metis assms(1) assms(2) differ_only_by_def)
definition not_free_var_of where
"not_free_var_of P x ⟷ (∀states states'.
(∀i. differ_only_by (fst (states i)) (fst (states' i)) x ∧ snd (states i) = snd (states' i))
⟶ (states ∈ P ⟷ states' ∈ P))"
lemma not_free_var_ofE:
assumes "not_free_var_of P x"
and "⋀i. differ_only_by (fst (states i)) (fst (states' i)) x"
and "⋀i. snd (states i) = snd (states' i)"
and "states ∈ P"
shows "states' ∈ P"
using not_free_var_of_def[of P x] assms by blast
subsection ‹Synchronized Rule for Branching›
definition combine where
"combine from_nat x P1 P2 S ⟷ P1 (Set.filter (λφ. fst φ x = from_nat 1) S) ∧ P2 (Set.filter (λφ. fst φ x = from_nat 2) S)"
lemma combineI:
assumes "P1 (Set.filter (λφ. fst φ x = from_nat 1) S) ∧ P2 (Set.filter (λφ. fst φ x = from_nat 2) S)"
shows "combine from_nat x P1 P2 S"
by (simp add: assms combine_def)
definition modify_lvar_to where
"modify_lvar_to x v φ = ((fst φ)(x := v), snd φ)"
lemma logical_var_in_sem_same:
assumes "⋀φ. φ ∈ S ⟹ fst φ x = a"
and "φ' ∈ sem C S"
shows "fst φ' x = a"
by (metis assms(1) assms(2) fst_conv in_sem)
lemma recover_after_sem:
assumes "a ≠ b"
and "⋀φ. φ ∈ S1 ⟹ fst φ x = a"
and "⋀φ. φ ∈ S2 ⟹ fst φ x = b"
shows "sem C S1 = Set.filter (λφ. fst φ x = a) (sem C (S1 ∪ S2))" (is "?A = ?B")
proof
have r: "sem C (S1 ∪ S2) = sem C S1 ∪ sem C S2"
by (simp add: sem_union)
moreover have r1: "⋀φ'. φ' ∈ sem C S1 ⟹ fst φ' x = a"
by (metis assms(2) fst_conv in_sem)
moreover have r2: "⋀φ'. φ' ∈ sem C S2 ⟹ fst φ' x = b"
by (metis assms(3) fst_conv in_sem)
show "?B ⊆ ?A"
proof (rule subsetPairI)
fix l σ
assume "(l, σ) ∈ Set.filter (λφ. fst φ x = a) (sem C (S1 ∪ S2))"
then show "(l, σ) ∈ sem C S1"
using assms(1) r r2 by auto
qed
show "?A ⊆ ?B"
by (simp add: r r1 subsetI)
qed
lemma injective_then_ok:
assumes "a ≠ b"
and "S1' = (modify_lvar_to x a) ` S1"
and "S2' = (modify_lvar_to x b) ` S2"
shows "Set.filter (λφ. fst φ x = a) (S1' ∪ S2') = S1'" (is "?A = ?B")
proof
show "?B ⊆ ?A"
proof (rule subsetI)
fix y assume "y ∈ S1'"
then have "fst y x = a" using modify_lvar_to_def assms(2)
by (metis (mono_tags, lifting) fst_conv fun_upd_same image_iff)
then show "y ∈ Set.filter (λφ. fst φ x = a) (S1' ∪ S2')"
by (simp add: ‹y ∈ S1'›)
qed
show "?A ⊆ ?B"
proof
fix y assume "y ∈ ?A"
then have "y ∉ S2'"
by (metis (mono_tags, lifting) assms(1) assms(3) fun_upd_same image_iff member_filter modify_lvar_to_def prod.sel(1))
then show "y ∈ ?B"
using ‹y ∈ Set.filter (λφ. fst φ x = a) (S1' ∪ S2')› by auto
qed
qed
definition not_free_var_hyper where
"not_free_var_hyper x P ⟷ (∀S v. P S ⟷ P ((modify_lvar_to x v) ` S))"
definition injective where
"injective f ⟷ (∀a b. a ≠ b ⟶ f a ≠ f b)"
lemma sem_of_modify_lvar:
"sem C ((modify_lvar_to r v) ` S) = (modify_lvar_to r v) ` (sem C S)" (is "?A = ?B")
proof
show "?A ⊆ ?B"
proof (rule subsetI)
fix y assume asm0: "y ∈ ?A"
then obtain x where "x ∈ (modify_lvar_to r v) ` S" "single_sem C (snd x) (snd y)" "fst x = fst y"
by (metis fst_conv in_sem snd_conv)
then obtain xx where "xx ∈ S" "x = modify_lvar_to r v xx"
by blast
then have "(fst xx, snd y) ∈ sem C S"
by (metis ‹⟨C, snd x⟩ → snd y› fst_conv in_sem modify_lvar_to_def prod.collapse snd_conv)
then show "y ∈ ?B"
by (metis ‹fst x = fst y› ‹x = modify_lvar_to r v xx› fst_eqD modify_lvar_to_def prod.exhaust_sel rev_image_eqI snd_eqD)
qed
show "?B ⊆ ?A"
proof (rule subsetI)
fix y assume "y ∈ modify_lvar_to r v ` sem C S"
then obtain yy where "y = modify_lvar_to r v yy" "yy ∈ sem C S"
by blast
then obtain x where "x ∈ S" "fst x = fst yy" "single_sem C (snd x) (snd yy)"
by (metis fst_conv in_sem snd_conv)
then have "fst (modify_lvar_to r v x) = fst y"
by (simp add: ‹y = modify_lvar_to r v yy› modify_lvar_to_def)
then show "y ∈ sem C (modify_lvar_to r v ` S)"
by (metis (mono_tags, lifting) ‹⟨C, snd x⟩ → snd yy› ‹x ∈ S› ‹y = modify_lvar_to r v yy› fst_conv
image_eqI in_sem modify_lvar_to_def snd_conv)
qed
qed
end