Theory PAL

(*
  File:      PAL.thy
  Author:    Asta Halkjær From

  This work is a formalization of public announcement logic.
  It includes proofs of soundness and completeness for variants of the axiom system
    PA + DIST! + NEC!.
  The completeness proofs build on the Epistemic Logic theory.
*)

theory PAL imports "Epistemic_Logic.Epistemic_Logic" begin

section ‹Syntax›

datatype 'i pfm
  = FF (‹⊥!›)
  | Pro' id (‹Pro!›)
  | Dis ‹'i pfm› ‹'i pfm› (infixr ‹∨!› 60)
  | Con ‹'i pfm› ‹'i pfm› (infixr ‹∧!› 65)
  | Imp ‹'i pfm› ‹'i pfm› (infixr ‹⟶!› 55)
  | K' 'i ‹'i pfm› (‹K!›)
  | Ann ‹'i pfm› ‹'i pfm› (‹[_]! _› [80, 80] 80)

abbreviation PIff :: ‹'i pfm ⇒ 'i pfm ⇒ 'i pfm› (infixr ‹⟷!› 55) where
  ‹p ⟷! q ≡ (p ⟶! q) ∧! (q ⟶! p)›

abbreviation PNeg (‹¬! _› [70] 70) where
  ‹¬! p ≡ p ⟶! ⊥!›

abbreviation PL (‹L!›) where
  ‹L! i p ≡ (¬! (K! i (¬! p)))›

primrec anns :: ‹'i pfm ⇒ 'i pfm set› where
  ‹anns ⊥! = {}›
| ‹anns (Pro! _) = {}›
| ‹anns (p ∨! q) = (anns p ∪ anns q)›
| ‹anns (p ∧! q) = (anns p ∪ anns q)›
| ‹anns (p ⟶! q) = (anns p ∪ anns q)›
| ‹anns (K! i p) = anns p›
| ‹anns ([r]! p) = {r} ∪ anns r ∪ anns p›

section ‹Semantics›

fun
  psemantics :: ‹('i, 'w) kripke ⇒ 'w ⇒ 'i pfm ⇒ bool› (‹_, _ ⊨! _› [50, 50, 50] 50) and
  restrict :: ‹('i, 'w) kripke ⇒ 'i pfm ⇒ ('i, 'w) kripke› (‹_[_!]› [50, 50] 50) where
  ‹M, w ⊨! ⊥! ⟷ False›
| ‹M, w ⊨! Pro! x ⟷ π M w x›
| ‹M, w ⊨! p ∨! q ⟷ M, w ⊨! p ∨ M, w ⊨! q›
| ‹M, w ⊨! p ∧! q ⟷ M, w ⊨! p ∧ M, w ⊨! q›
| ‹M, w ⊨! p ⟶! q ⟷ M, w ⊨! p ⟶ M, w ⊨! q›
| ‹M, w ⊨! K! i p ⟷ (∀v ∈ 𝒲 M ∩ 𝒦 M i w. M, v ⊨! p)›
| ‹M, w ⊨! [r]! p ⟷ M, w ⊨! r ⟶ M[r!], w ⊨! p›
| ‹M[r!] = M ⦇𝒲 := {w. w ∈ 𝒲 M ∧ M, w ⊨! r}⦈›

abbreviation validPStar :: ‹(('i, 'w) kripke ⇒ bool) ⇒ 'i pfm set ⇒ 'i pfm ⇒ bool›
  (‹_; _ ⊫!⋆ _› [50, 50, 50] 50) where
  ‹P; G ⊫!⋆ p ≡ ∀M. P M ⟶ (∀w ∈ 𝒲 M. (∀q ∈ G. M, w ⊨! q) ⟶ M, w ⊨! p)›

primrec static :: ‹'i pfm ⇒ bool› where
  ‹static ⊥! = True›
| ‹static (Pro! _) = True›
| ‹static (p ∨! q) = (static p ∧ static q)›
| ‹static (p ∧! q) = (static p ∧ static q)›
| ‹static (p ⟶! q) = (static p ∧ static q)›
| ‹static (K! i p) = static p›
| ‹static ([r]! p) = False›

primrec lower :: ‹'i pfm ⇒ 'i fm› where
  ‹lower ⊥! = ⊥›
| ‹lower (Pro! x) = Pro x›
| ‹lower (p ∨! q) = (lower p ∨ lower q)›
| ‹lower (p ∧! q) = (lower p ∧ lower q)›
| ‹lower (p ⟶! q) = (lower p ⟶ lower q)›
| ‹lower (K! i p) = K i (lower p)›
| ‹lower ([r]! p) = undefined›

primrec lift :: ‹'i fm ⇒ 'i pfm› where
  ‹lift ⊥ = ⊥!›
| ‹lift (Pro x) = Pro! x›
| ‹lift (p ∨ q) = (lift p ∨! lift q)›
| ‹lift (p ∧ q) = (lift p ∧! lift q)›
| ‹lift (p ⟶ q) = (lift p ⟶! lift q)›
| ‹lift (K i p) = K! i (lift p)›

lemma lower_semantics:
  assumes ‹static p›
  shows ‹(M, w ⊨ lower p) ⟷ (M, w ⊨! p)›
  using assms by (induct p arbitrary: w) simp_all

lemma lift_semantics: ‹(M, w ⊨ p) ⟷ (M, w ⊨! lift p)›
  by (induct p arbitrary: w) simp_all

lemma lower_lift: ‹lower (lift p) = p›
  by (induct p) simp_all

lemma lift_lower: ‹static p ⟹ lift (lower p) = p›
  by (induct p) simp_all

section ‹Soundness of Reduction›

primrec reduce' :: ‹'i pfm ⇒ 'i pfm ⇒ 'i pfm› where
  ‹reduce' r ⊥! = (r ⟶! ⊥!)›
| ‹reduce' r (Pro! x) = (r ⟶! Pro! x)›
| ‹reduce' r (p ∨! q) = (reduce' r p ∨! reduce' r q)›
| ‹reduce' r (p ∧! q) = (reduce' r p ∧! reduce' r q)›
| ‹reduce' r (p ⟶! q) = (reduce' r p ⟶! reduce' r q)›
| ‹reduce' r (K! i p) = (r ⟶! K! i (reduce' r p))›
| ‹reduce' r ([p]! q) = undefined›

primrec reduce :: ‹'i pfm ⇒ 'i pfm› where
  ‹reduce ⊥! = ⊥!›
| ‹reduce (Pro! x) = Pro! x›
| ‹reduce (p ∨! q) = (reduce p ∨! reduce q)›
| ‹reduce (p ∧! q) = (reduce p ∧! reduce q)›
| ‹reduce (p ⟶! q) = (reduce p ⟶! reduce q)›
| ‹reduce (K! i p) = K! i (reduce p)›
| ‹reduce ([r]! p) = reduce' (reduce r) (reduce p)›

lemma static_reduce': ‹static p ⟹ static r ⟹ static (reduce' r p)›
  by (induct p) simp_all

lemma static_reduce: ‹static (reduce p)›
  by (induct p) (simp_all add: static_reduce')

lemma reduce'_semantics:
  assumes ‹static q›
  shows ‹(M, w ⊨! [p]! q) = (M, w ⊨! reduce' p q)›
  using assms by (induct q arbitrary: w) auto

lemma reduce_semantics: ‹M, w ⊨! p ⟷ M, w ⊨! reduce p›
proof (induct p arbitrary: M w)
  case (Ann p q)
  then show ?case
    using reduce'_semantics static_reduce by fastforce
qed simp_all

section ‹Chains of Implications›

primrec implyP :: ‹'i pfm list ⇒ 'i pfm ⇒ 'i pfm› (infixr ‹↝!› 56) where
  ‹([] ↝! q) = q›
| ‹(p # ps ↝! q) = (p ⟶! ps ↝! q)›

lemma lift_implyP: ‹lift (ps ↝ q) = (map lift ps ↝! lift q)›
  by (induct ps) auto

lemma reduce_implyP: ‹reduce (ps ↝! q) = (map reduce ps ↝! reduce q)›
  by (induct ps) auto

section ‹Proof System›

primrec peval :: ‹(id ⇒ bool) ⇒ ('i pfm ⇒ bool) ⇒ 'i pfm ⇒ bool› where
  ‹peval _ _ ⊥! = False›
| ‹peval g _ (Pro! x) = g x›
| ‹peval g h (p ∨! q) = (peval g h p ∨ peval g h q)›
| ‹peval g h (p ∧! q) = (peval g h p ∧ peval g h q)›
| ‹peval g h (p ⟶! q) = (peval g h p ⟶ peval g h q)›
| ‹peval _ h (K! i p) = h (K! i p)›
| ‹peval _ h ([r]! p) = h ([r]! p)›

abbreviation ‹ptautology p ≡ ∀g h. peval g h p›

inductive PAK :: ‹('i pfm ⇒ bool) ⇒ ('i pfm ⇒ bool) ⇒ 'i pfm ⇒ bool›
  (‹_; _ ⊢! _› [50, 50, 50] 50)
  for A B :: ‹'i pfm ⇒ bool› where
    PA1: ‹ptautology p ⟹ A; B ⊢! p›
  | PA2: ‹A; B ⊢! K! i p ∧! K! i (p ⟶! q) ⟶! K! i q›
  | PAx: ‹A p ⟹ A; B ⊢! p›
  | PR1: ‹A; B ⊢! p ⟹ A; B ⊢! p ⟶! q ⟹ A; B ⊢! q›
  | PR2: ‹A; B ⊢! p ⟹ A; B ⊢! K! i p›
  | PAnn: ‹A; B ⊢! p ⟹ B r ⟹ A; B ⊢! [r]! p›
  | PFF: ‹A; B ⊢! [r]! ⊥! ⟷! (r ⟶! ⊥!)›
  | PPro: ‹A; B ⊢! [r]! Pro! x ⟷! (r ⟶! Pro! x)›
  | PDis: ‹A; B ⊢! [r]! (p ∨! q) ⟷! [r]! p ∨! [r]! q›
  | PCon: ‹A; B ⊢! [r]! (p ∧! q) ⟷! [r]! p ∧! [r]! q›
  | PImp: ‹A; B ⊢! [r]! (p ⟶! q) ⟷! ([r]! p ⟶! [r]! q)›
  | PK: ‹A; B ⊢! [r]! K! i p ⟷! (r ⟶! K! i ([r]! p))›

abbreviation PAK_assms (‹_; _; _ ⊢! _› [50, 50, 50, 50] 50) where
  ‹A; B; G ⊢! p ≡ ∃qs. set qs ⊆ G ∧ (A; B ⊢! qs ↝! p)›

lemma eval_peval: ‹eval h (g o lift) p = peval h g (lift p)›
  by (induct p) simp_all

lemma tautology_ptautology: ‹tautology p ⟹ ptautology (lift p)›
  using eval_peval by blast

theorem AK_PAK: ‹A o lift ⊢ p ⟹ A; B ⊢! lift p›
  by (induct p rule: AK.induct) (auto intro: PAK.intros(1-5) simp: tautology_ptautology)

abbreviation validP
  :: ‹(('i, 'i fm set) kripke ⇒ bool) ⇒ 'i pfm set ⇒ 'i pfm ⇒ bool›
  (‹_; _ ⊫! _› [50, 50, 50] 50)
  where ‹P; G ⊫! p ≡ P; G ⊫!⋆ p›

lemma set_map_inv:
  assumes ‹set xs ⊆ f ` X›
  shows ‹∃ys. set ys ⊆ X ∧ map f ys = xs›
  using assms
proof (induct xs)
  case (Cons x xs)
  then obtain ys where ‹set ys ⊆ X› ‹map f ys = xs›
    by auto
  moreover obtain y where ‹y ∈ X› ‹f y = x›
    using Cons.prems by auto
  ultimately have ‹set (y # ys) ⊆ X› ‹map f (y # ys) = x # xs›
    by simp_all
  then show ?case
    by meson
qed simp

lemma strong_static_completeness':
  assumes ‹static p› and ‹∀q ∈ G. static q› and ‹P; G ⊫! p›
    and ‹P; lower ` G ⊫⋆ lower p ⟹ A o lift; lower ` G ⊢ lower p›
  shows ‹A; B; G ⊢! p›
proof -
  have ‹P; lower ` G ⊫⋆ lower p›
    using assms by (simp add: lower_semantics)
  then have ‹A o lift; lower ` G ⊢ lower p›
    using assms(4) by blast
  then obtain qs where ‹set qs ⊆ G› and ‹A o lift ⊢ map lower qs ↝ lower p›
    using set_map_inv by blast
  then have ‹A; B ⊢! lift (map lower qs ↝ lower p)›
    using AK_PAK by fast
  then have ‹A; B ⊢! map lift (map lower qs) ↝! lift (lower p)›
    using lift_implyP by metis
  then have ‹A; B ⊢! map (lift o lower) qs ↝! lift (lower p)›
    by simp
  then show ?thesis
    using assms(1-2) ‹set qs ⊆ G› lift_lower
    by (metis (mono_tags, lifting) comp_apply map_idI subset_eq)
qed

theorem strong_static_completeness:
  assumes ‹static p› and ‹∀q ∈ G. static q› and ‹P; G ⊫! p›
    and ‹⋀G p. P; G ⊫ p ⟹ A o lift; G ⊢ p›
  shows ‹A; B; G ⊢! p›
  using strong_static_completeness' assms .

corollary static_completeness':
  assumes ‹static p› and ‹P; {} ⊫!⋆ p›
    and ‹P; {} ⊫ lower p ⟹ A o lift ⊢ lower p›
  shows ‹A; B ⊢! p›
  using assms strong_static_completeness'[where G=‹{}› and p=p] by simp

corollary static_completeness:
  assumes ‹static p› and ‹P; {} ⊫!⋆ p› and ‹⋀p. P; {} ⊫ p ⟹ A o lift ⊢ p›
  shows ‹A; B ⊢! p›
  using static_completeness' assms .

corollary
  assumes ‹static p› ‹(λ_. True); {} ⊫! p›
  shows ‹A; B ⊢! p›
  using assms static_completeness[where P=‹λ_. True› and p=p] completenessA by blast

section ‹Soundness›

lemma peval_semantics:
  ‹peval (val w) (λq. ⦇𝒲 = W, 𝒦 = r, π = val⦈, w ⊨! q) p = (⦇𝒲 = W, 𝒦 = r, π = val⦈, w ⊨! p)›
  by (induct p) simp_all

lemma ptautology:
  assumes ‹ptautology p›
  shows ‹M, w ⊨! p›
proof -
  from assms have ‹peval (g w) (λq. ⦇𝒲 = W, 𝒦 = r, π = g⦈, w ⊨! q) p› for W g r
    by simp
  then have ‹⦇𝒲 = W, 𝒦 = r, π = g⦈, w ⊨! p› for W g r
    using peval_semantics by fast
  then show ‹M, w ⊨! p›
    by (metis kripke.cases)
qed

theorem soundnessP:
  assumes
    ‹⋀M p w. A p ⟹ P M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
    ‹⋀M r. P M ⟹ B r ⟹ P (M[r!])›
  shows ‹A; B ⊢! p ⟹ P M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
proof (induct p arbitrary: M w rule: PAK.induct)
  case (PAnn p r)
  then show ?case
    using assms by simp
qed (simp_all add: assms ptautology)

corollary ‹(λ_. False); B ⊢! p ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  using soundnessP[where P=‹λ_. True›] by metis

section ‹Strong Soundness›

lemma ptautology_imply_superset:
  assumes ‹set ps ⊆ set qs›
  shows ‹ptautology (ps ↝! r ⟶! qs ↝! r)›
proof (rule ccontr)
  assume ‹¬ ?thesis›
  then obtain g h where ‹¬ peval g h (ps ↝! r ⟶! qs ↝! r)›
    by blast
  then have ‹peval g h (ps ↝! r)› ‹¬ peval g h (qs ↝! r)›
    by simp_all
  then consider (np) ‹∃p ∈ set ps. ¬ peval g h p› | (r) ‹∀p ∈ set ps. peval g h p› ‹peval g h r›
    by (induct ps) auto
  then show False
  proof cases
    case np
    then have ‹∃p ∈ set qs. ¬ peval g h p›
      using ‹set ps ⊆ set qs› by blast
    then have ‹peval g h (qs ↝! r)›
      by (induct qs) simp_all
    then show ?thesis
      using ‹¬ peval g h (qs ↝! r)› by blast
  next
    case r
    then have ‹peval g h (qs ↝! r)›
      by (induct qs) simp_all
    then show ?thesis
      using ‹¬ peval g h (qs ↝! r)› by blast
  qed
qed

lemma PK_imply_weaken:
  assumes ‹A; B ⊢! ps ↝! q› ‹set ps ⊆ set ps'›
  shows ‹A; B ⊢! ps' ↝! q›
proof -
  have ‹ptautology (ps ↝! q ⟶! ps' ↝! q)›
    using ‹set ps ⊆ set ps'› ptautology_imply_superset by blast
  then have ‹A; B ⊢! ps ↝! q ⟶! ps' ↝! q›
    using PA1 by blast
  then show ?thesis
    using ‹A; B ⊢! ps ↝! q› PR1 by blast
qed

lemma implyP_append: ‹(ps @ ps' ↝! q) = (ps ↝! ps' ↝! q)›
  by (induct ps) simp_all

lemma PK_ImpI:
  assumes ‹A; B ⊢! p # G ↝! q›
  shows ‹A; B ⊢! G ↝! (p ⟶! q)›
proof -
  have ‹set (p # G) ⊆ set (G @ [p])›
    by simp
  then have ‹A; B ⊢! G @ [p] ↝! q›
    using assms PK_imply_weaken by blast
  then have ‹A; B ⊢! G ↝! [p] ↝! q›
    using implyP_append by metis
  then show ?thesis
    by simp
qed

corollary soundness_implyP:
  assumes
    ‹⋀M p w. A p ⟹ P M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
    ‹⋀M r. P M ⟹ B r ⟹ P (M[r!])›
  shows ‹A; B ⊢! qs ↝! p ⟹ P M ⟹ w ∈ 𝒲 M ⟹ ∀q ∈ set qs. M, w ⊨! q ⟹ M, w ⊨! p›
proof (induct qs arbitrary: p)
  case Nil
  then show ?case
    using soundnessP[of A P B p M w] assms by simp
next
  case (Cons q qs)
  then show ?case
    using PK_ImpI by fastforce
qed

theorem strong_soundnessP:
  assumes
    ‹⋀M w p. A p ⟹ P M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
    ‹⋀M r. P M ⟹ B r ⟹ P (M[r!])›
  shows ‹A; B; G ⊢! p ⟹ P; G ⊫!⋆ p›
proof safe
  fix qs w and M :: ‹('a, 'b) kripke›
  assume ‹A; B ⊢! qs ↝! p›
  moreover assume ‹set qs ⊆ G› ‹∀q ∈ G. M, w ⊨! q›
  then have ‹∀q ∈ set qs. M, w ⊨! q›
    using ‹set qs ⊆ G› by blast
  moreover assume ‹P M› ‹w ∈ 𝒲 M›
  ultimately show ‹M, w ⊨! p›
    using soundness_implyP[of A P B qs p] assms by blast
qed

section ‹Completeness›

lemma ConE:
  assumes ‹A; B ⊢! p ∧! q›
  shows ‹A; B ⊢! p› ‹A; B ⊢! q›
  using assms by (metis PA1 PR1 peval.simps(4-5))+

lemma Iff_Dis:
  assumes ‹A; B ⊢! p ⟷! p'› ‹A; B ⊢! q ⟷! q'›
  shows ‹A; B ⊢! ((p ∨! q) ⟷! (p' ∨! q'))›
proof -
  have ‹A; B ⊢! (p ⟷! p') ⟶! (q ⟷! q') ⟶! ((p ∨! q) ⟷! (p' ∨! q'))›
    by (simp add: PA1)
  then show ?thesis
    using assms PR1 by blast
qed

lemma Iff_Con:
  assumes ‹A; B ⊢! p ⟷! p'› ‹A; B ⊢! q ⟷! q'›
  shows ‹A; B ⊢! (p ∧! q) ⟷! (p' ∧! q')›
proof -
  have ‹A; B ⊢! (p ⟷! p') ⟶! (q ⟷! q') ⟶! ((p ∧! q) ⟷! (p' ∧! q'))›
    by (simp add: PA1)
  then show ?thesis
    using assms PR1 by blast
qed

lemma Iff_Imp:
  assumes ‹A; B ⊢! p ⟷! p'› ‹A; B ⊢! q ⟷! q'›
  shows ‹A; B ⊢! ((p ⟶! q) ⟷! (p' ⟶! q'))›
proof -
  have ‹A; B ⊢! (p ⟷! p') ⟶! (q ⟷! q') ⟶! ((p ⟶! q) ⟷! (p' ⟶! q'))›
    by (simp add: PA1)
  then show ?thesis
    using assms PR1 by blast
qed

lemma Iff_sym: ‹(A; B ⊢! p ⟷! q) = (A; B ⊢! q ⟷! p)›
proof -
  have ‹A; B ⊢! (p ⟷! q) ⟷! (q ⟷! p)›
    by (simp add: PA1)
  then show ?thesis
    using PR1 ConE by blast
qed

lemma Iff_Iff:
  assumes ‹A; B ⊢! p ⟷! p'› ‹A; B ⊢! p ⟷! q›
  shows ‹A; B ⊢! p' ⟷! q›
proof -
  have ‹ptautology ((p ⟷! p') ⟶! (p ⟷! q) ⟶! (p' ⟷! q))›
    by (metis peval.simps(4-5))
  with PA1 have ‹A; B ⊢! (p ⟷! p') ⟶! (p ⟷! q) ⟶! (p' ⟷! q)› .
  then show ?thesis
    using assms PR1 by blast
qed

lemma K'_A2': ‹A; B ⊢! K! i (p ⟶! q) ⟶! K! i p ⟶! K! i q›
proof -
  have ‹A; B ⊢! K! i p ∧! K! i (p ⟶! q) ⟶! K! i q›
    using PA2 by fast
  moreover have ‹A; B ⊢! (P ∧! Q ⟶! R) ⟶! (Q ⟶! P ⟶! R)› for P Q R
    by (simp add: PA1)
  ultimately show ?thesis
    using PR1 by fast
qed

lemma K'_map:
  assumes ‹A; B ⊢! p ⟶! q›
  shows ‹A; B ⊢! K! i p ⟶! K! i q›
proof -
  note ‹A; B ⊢! p ⟶! q›
  then have ‹A; B ⊢! K! i (p ⟶! q)›
    using PR2 by fast
  moreover have ‹A; B ⊢! K! i (p ⟶! q) ⟶! K! i p ⟶! K! i q›
    using K'_A2' by fast
  ultimately show ?thesis
    using PR1 by fast
qed

lemma ConI:
  assumes ‹A; B ⊢! p› ‹A; B ⊢! q›
  shows ‹A; B ⊢! p ∧! q›
proof -
  have ‹A; B ⊢! p ⟶! q ⟶! p ∧! q›
    by (simp add: PA1)
  then show ?thesis
    using assms PR1 by blast
qed

lemma Iff_wk:
  assumes ‹A; B ⊢! p ⟷! q›
  shows ‹A; B ⊢! (r ⟶! p) ⟷! (r ⟶! q)›
proof -
  have ‹A; B ⊢! (p ⟷! q) ⟶! ((r ⟶! p) ⟷! (r ⟶! q))›
    by (simp add: PA1)
  then show ?thesis
    using assms PR1 by blast
qed

lemma Iff_reduce':
  assumes ‹static p›
  shows ‹A; B ⊢! [r]! p ⟷! reduce' r p›
  using assms
proof (induct p rule: pfm.induct)
  case FF
  then show ?case
    by (simp add: PFF)
next
  case (Pro' x)
  then show ?case
    by (simp add: PPro)
next
  case (Dis p q)
  then have ‹A; B ⊢! [r]! p ∨! [r]! q ⟷! reduce' r (p ∨! q)›
    using Iff_Dis by fastforce
  moreover have ‹A; B ⊢! ([r]! p ∨! [r]! q) ⟷! ([r]! (p ∨! q))›
    using PDis Iff_sym by fastforce
  ultimately show ?case
    using PA1 PR1 Iff_Iff by blast
next
  case (Con p q)
  then have ‹A; B ⊢! [r]! p ∧! [r]! q ⟷! reduce' r (p ∧! q)›
    using Iff_Con by fastforce
  moreover have ‹A; B ⊢! ([r]! p ∧! [r]! q) ⟷! ([r]! (p ∧! q))›
    using PCon Iff_sym by fastforce
  ultimately show ?case
    using PA1 PR1 Iff_Iff by blast
next
  case (Imp p q)
  then have ‹A; B ⊢! ([r]! p ⟶! [r]! q) ⟷! reduce' r (p ⟶! q)›
    using Iff_Imp by fastforce
  moreover have ‹A; B ⊢! ([r]! p ⟶! [r]! q) ⟷! ([r]! (p ⟶! q))›
    using PImp Iff_sym by fastforce
  ultimately show ?case
    using PA1 PR1 Iff_Iff by blast
next
  case (K' i p)
  then have ‹A; B ⊢! [r]! p ⟷! reduce' r p›
    by simp
  then have ‹A; B ⊢! K! i ([r]! p) ⟷! K! i (reduce' r p)›
    using K'_map ConE ConI by metis
  moreover have ‹A; B ⊢! [r]! K! i p ⟷! r ⟶! K! i ([r]! p)›
    using PK .
  ultimately have ‹A; B ⊢! [r]! K! i p ⟷! r ⟶! K! i (reduce' r p)›
    by (meson Iff_Iff Iff_sym Iff_wk)
  then show ?case
    by simp
next
  case (Ann r p)
  then show ?case
    by simp
qed

lemma Iff_Ann1:
  assumes r: ‹A; B ⊢! r ⟷! r'› and ‹static p›
  shows ‹A; B ⊢! [r]! p ⟷! [r']! p›
  using assms(2-)
proof (induct p)
  case FF
  have ‹A; B ⊢! (r ⟷! r') ⟶! ((r ⟶! ⊥!) ⟷! (r' ⟶! ⊥!))›
    by (auto intro: PA1)
  then have ‹A; B ⊢! (r ⟶! ⊥!) ⟷! (r' ⟶! ⊥!)›
    using r PR1 by blast
  then show ?case
    by (meson PFF Iff_Iff Iff_sym)
next
  case (Pro' x)
  have ‹A; B ⊢! (r ⟷! r') ⟶! ((r ⟶! Pro! x) ⟷! (r' ⟶! Pro! x))›
    by (auto intro: PA1)
  then have ‹A; B ⊢! (r ⟶! Pro! x) ⟷! (r' ⟶! Pro! x)›
    using r PR1 by blast
  then show ?case
    by (meson PPro Iff_Iff Iff_sym)
next
  case (Dis p q)
  then have ‹A; B ⊢! [r]! p ∨! [r]! q ⟷! [r']! p ∨! [r']! q›
    by (simp add: Iff_Dis)
  then show ?case
    by (meson PDis Iff_Iff Iff_sym)
next
  case (Con p q)
  then have ‹A; B ⊢! [r]! p ∧! [r]! q ⟷! [r']! p ∧! [r']! q›
    by (simp add: Iff_Con)
  then show ?case
    by (meson PCon Iff_Iff Iff_sym)
next
  case (Imp p q)
  then have ‹A; B ⊢! ([r]! p ⟶! [r]! q) ⟷! ([r']! p ⟶! [r']! q)›
    by (simp add: Iff_Imp)
  then show ?case
    by (meson PImp Iff_Iff Iff_sym)
next
  case (K' i p)
  then have ‹A; B ⊢! [r]! p ⟷! [r']! p›
    by simp
  then have ‹A; B ⊢! K! i ([r]! p) ⟷! K! i ([r']! p)›
    using K'_map ConE ConI by metis
  then show ?case
    by (meson Iff_Iff Iff_Imp Iff_sym PK r)
next
  case (Ann s p)
  then show ?case
    by simp
qed

lemma Iff_Ann2:
  assumes ‹A; B ⊢! p ⟷! p'› and ‹B r›
  shows ‹A; B ⊢! [r]! p ⟷! [r]! p'›
  using assms PAnn ConE ConI PImp PR1 by metis

lemma Iff_reduce:
  assumes ‹∀r ∈ anns p. B r›
  shows ‹A; B ⊢! p ⟷! reduce p›
  using assms
proof (induct p)
  case (Dis p q)
  then show ?case
    by (simp add: Iff_Dis)
next
  case (Con p q)
  then show ?case
    by (simp add: Iff_Con)
next
  case (Imp p q)
  then show ?case
    by (simp add: Iff_Imp)
next
  case (K' i p)
  then have
    ‹A; B ⊢! K! i p ⟶! K! i (reduce p)›
    ‹A; B ⊢! K! i (reduce p) ⟶! K! i p›
    using K'_map ConE by fastforce+
  then have ‹A; B ⊢! K! i p ⟷! K! i (reduce p)›
    using ConI by blast
  then show ?case
    by simp
next
  case (Ann r p)
  then have ‹B r›
    by simp
  have ‹A; B ⊢! [reduce r]! reduce p ⟷! reduce' (reduce r) (reduce p)›
    using Iff_reduce' static_reduce by blast
  moreover have ‹A; B ⊢! [r]! reduce p ⟷! [reduce r]! reduce p›
    using Ann Iff_Ann1 static_reduce by fastforce
  ultimately have ‹A; B ⊢! [r]! reduce p ⟷! reduce' (reduce r) (reduce p)›
    using Iff_Iff Iff_sym by blast
  moreover have ‹∀r ∈ anns p. B r›
    using Ann.prems by simp
  then have ‹A; B ⊢! p ⟷! reduce p›
    using Ann.hyps(2) by blast
  then have ‹A; B ⊢! [r]! reduce p ⟷! [r]! p›
    using ‹B r› Iff_Ann2 Iff_sym by blast
  ultimately have ‹A; B ⊢! [r]! p ⟷! reduce' (reduce r) (reduce p)›
    using Iff_Iff by blast
  then show ?case
    by simp
qed (simp_all add: PA1)

lemma anns_implyP [simp]:
  ‹anns (ps ↝! q) =  anns q ∪ (⋃p ∈ set ps. anns p)›
  by (induct ps) auto

lemma strong_completenessP':
  assumes ‹P; G ⊫! p›
    and ‹∀r ∈ anns p. B r› ‹∀q ∈ G. ∀r ∈ anns q. B r›
    and ‹P; lower ` reduce ` G ⊫⋆ lower (reduce p) ⟹
      A o lift; lower ` reduce ` G ⊢ lower (reduce p)›
  shows ‹A; B; G ⊢! p›
proof -
  have ‹P; reduce ` G ⊫!⋆ reduce p›
    using assms(1) reduce_semantics by fast
  moreover have ‹static (reduce p)› ‹∀q ∈ reduce ` G. static q›
    using static_reduce by fast+
  ultimately have ‹A; B; reduce ` G ⊢! reduce p›
    using assms(4) strong_static_completeness'[where G=‹reduce ` G› and p=‹reduce p›]
    by presburger
  then have ‹∃qs. set qs ⊆ G ∧ (A; B ⊢! map reduce qs ↝! reduce p)›
    using set_map_inv by fast
  then obtain qs where qs: ‹set qs ⊆ G› and ‹A; B ⊢! map reduce qs ↝! reduce p›
    by blast
  then have ‹A; B ⊢! reduce (qs ↝! p)›
    using reduce_implyP by metis
  moreover have ‹∀r ∈ anns (qs ↝! p). B r›
    using assms(2-3) qs by auto
  then have ‹A; B ⊢! qs ↝! p ⟷! reduce (qs ↝! p)›
    using Iff_reduce by blast
  ultimately have ‹A; B ⊢! qs ↝! p›
    using ConE(2) PR1 by blast
  then show ?thesis
    using qs by blast
qed

theorem strong_completenessP:
  assumes ‹P; G ⊫! p›
    and ‹∀r ∈ anns p. B r› ‹∀q ∈ G. ∀r ∈ anns q. B r›
    and ‹⋀G p. P; G ⊫⋆ p ⟹ A o lift; G ⊢ p›
  shows ‹A; B; G ⊢! p›
  using strong_completenessP' assms .

theorem mainP:
  assumes ‹⋀M w p. A p ⟹ P M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
    and ‹⋀M r. P M ⟹ B r ⟹ P (M[r!])›
    and ‹∀r ∈ anns p. B r› ‹∀q ∈ G. ∀r ∈ anns q. B r›
    and ‹⋀G p. P; G ⊫⋆ p ⟹ A o lift; G ⊢ p›
  shows ‹P; G ⊫! p ⟷ A; B; G ⊢! p›
  using strong_soundnessP[of A P B G p] strong_completenessP[of P G p B A] assms by blast

corollary strong_completenessPB:
  assumes ‹P; G ⊫! p›
    and ‹⋀G p. P; G ⊫⋆ p ⟹ A o lift; G ⊢ p›
  shows ‹A; (λ_. True); G ⊢! p›
  using strong_completenessP[where B=‹λ_. True›] assms by blast

corollary completenessP':
  assumes ‹P; {} ⊫! p›
    and ‹∀r ∈ anns p. B r›
    and ‹⋀p. P; {} ⊫ lower p ⟹ A o lift ⊢ lower p›
  shows ‹A; B ⊢! p›
  using assms strong_completenessP'[where P=P and G=‹{}›] by simp

corollary completenessP:
  assumes ‹P; {} ⊫! p›
    and ‹∀r ∈ anns p. B r›
    and ‹⋀p. P; {} ⊫ p ⟹ A o lift ⊢ p›
  shows ‹A; B ⊢! p›
  using completenessP' assms .

corollary completenessPA:
  assumes ‹(λ_. True); {} ⊫! p›
  shows ‹A; (λ_. True) ⊢! p›
  using assms completenessP[of ‹λ_. True› p ‹λ_. True›] completenessA by blast

section ‹System PAL + K›

abbreviation SystemPK (‹_ ⊢!K _› [50, 50] 50) where
  ‹G ⊢!K p ≡ (λ_. False); (λ_. True); G ⊢! p›

lemma strong_soundnessPK: ‹G ⊢!K p ⟹ (λ_. True); G ⊫!⋆ p›
  using strong_soundnessP[of ‹λ_. False› ‹λ_. True›] by fast

abbreviation validPK (‹_ ⊫!K _› [50, 50] 50) where
  ‹G ⊫!K p ≡ (λ_. True); G ⊫! p›

lemma strong_completenessPK:
  assumes ‹G ⊫!K p›
  shows ‹G ⊢!K p›
  using strong_completenessPB assms strong_completenessK unfolding comp_apply .

theorem mainPK: ‹G ⊫!K p ⟷ G ⊢!K p›
  using strong_soundnessPK[of G p] strong_completenessPK[of G p] by fast

corollary ‹G ⊫!K p ⟹ (λ_. True); G ⊫!⋆ p›
  using strong_soundnessPK[of G p] strong_completenessPK[of G p] by fast

section ‹System PAL + T›

text ‹Also known as System PAL + M›

inductive AxPT :: ‹'i pfm ⇒ bool› where
  ‹AxPT (K! i p ⟶! p)›

abbreviation SystemPT (‹_ ⊢!T _› [50, 50] 50) where
  ‹G ⊢!T p ≡ AxPT; (λ_. True); G ⊢! p›

lemma soundness_AxPT: ‹AxPT p ⟹ reflexive M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  unfolding reflexive_def by (induct p rule: AxPT.induct) simp

lemma reflexive_restrict: ‹reflexive M ⟹ reflexive (M[r!])›
  unfolding reflexive_def by simp

lemma strong_soundnessPT: ‹G ⊢!T p ⟹ reflexive; G ⊫!⋆ p›
  using strong_soundnessP[of AxPT reflexive ‹λ_. True› G p]
    soundness_AxPT reflexive_restrict by fast

lemma AxT_AxPT: ‹AxT = AxPT o lift›
  unfolding comp_apply using lower_lift
  by (metis AxPT.simps AxT.simps lift.simps(5-6) lower.simps(5-6))

abbreviation validPT (‹_ ⊫!T _› [50, 50] 50) where
  ‹G ⊫!T p ≡ reflexive; G ⊫! p›

lemma strong_completenessPT:
  assumes ‹G ⊫!T p›
  shows ‹G ⊢!T p›
  using strong_completenessPB assms strong_completenessT unfolding AxT_AxPT .

theorem mainPT: ‹G ⊫!T p ⟷ G ⊢!T p›
  using strong_soundnessPT[of G p] strong_completenessPT[of G p] by fast

corollary ‹G ⊫!T p ⟹ reflexive; G ⊫!⋆ p›
  using strong_soundnessPT[of G p] strong_completenessPT[of G p] by fast

section ‹System PAL + KB›

inductive AxPB :: ‹'i pfm ⇒ bool› where
  ‹AxPB (p ⟶! K! i (L! i p))›

abbreviation SystemPKB (‹_ ⊢!KB _› [50, 50] 50) where
  ‹G ⊢!KB p ≡ AxPB; (λ_. True); G ⊢! p›

lemma soundness_AxPB: ‹AxPB p ⟹ symmetric M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  unfolding symmetric_def by (induct p rule: AxPB.induct) auto

lemma symmetric_restrict: ‹symmetric M ⟹ symmetric (M[r!])›
  unfolding symmetric_def by simp

lemma strong_soundnessPKB: ‹G ⊢!KB p ⟹ symmetric; G ⊫!⋆ p›
  using strong_soundnessP[of AxPB symmetric ‹λ_. True› G p]
    soundness_AxPB symmetric_restrict by fast

lemma AxB_AxPB: ‹AxB = AxPB o lift›
proof
  fix p :: ‹'i fm›
  show ‹AxB p = (AxPB ∘ lift) p›
    unfolding comp_apply using lower_lift
    by (smt (verit, best) AxB.simps AxPB.simps lift.simps(1, 5-6) lower.simps(5-6))
qed

abbreviation validPKB (‹_ ⊫!KB _› [50, 50] 50) where
  ‹G ⊫!KB p ≡ symmetric; G ⊫! p›

lemma strong_completenessPKB:
  assumes ‹G ⊫!KB p›
  shows ‹G ⊢!KB p›
  using strong_completenessPB assms strong_completenessKB unfolding AxB_AxPB .

theorem mainPKB: ‹G ⊫!KB p ⟷ G ⊢!KB p›
  using strong_soundnessPKB[of G p] strong_completenessPKB[of G p] by fast

corollary ‹G ⊫!KB p ⟹ symmetric; G ⊫!⋆ p›
  using strong_soundnessPKB[of G p] strong_completenessPKB[of G p] by fast

section ‹System PAL + K4›

inductive AxP4 :: ‹'i pfm ⇒ bool› where
  ‹AxP4 (K! i p ⟶! K! i (K! i p))›

abbreviation SystemPK4 (‹_ ⊢!K4 _› [50, 50] 50) where
  ‹G ⊢!K4 p ≡ AxP4; (λ_. True); G ⊢! p›

lemma pos_introspection:
  assumes ‹transitive M› ‹w ∈ 𝒲 M›
  shows ‹M, w ⊨! (K! i p ⟶! K! i (K! i p))›
proof -
  { assume ‹M, w ⊨! K! i p›
    then have ‹∀v ∈ 𝒲 M ∩ 𝒦 M i w. M, v ⊨! p›
      by simp
    then have ‹∀v ∈ 𝒲 M ∩ 𝒦 M i w. ∀u ∈ 𝒲 M ∩ 𝒦 M i v. M, u ⊨! p›
      using ‹transitive M› ‹w ∈ 𝒲 M› unfolding transitive_def by blast
    then have ‹∀v ∈ 𝒲 M ∩ 𝒦 M i w. M, v ⊨! K! i p›
      by simp
    then have ‹M, w ⊨! K! i (K! i p)›
      by simp }
  then show ?thesis
    by fastforce
qed

lemma soundness_AxP4: ‹AxP4 p ⟹ transitive M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  by (induct p rule: AxP4.induct) (metis pos_introspection)

lemma transitive_restrict: ‹transitive M ⟹ transitive (M[r!])›
  unfolding transitive_def by (cases M) (metis (no_types, lifting) frame.select_convs(1-2)
      frame.update_convs(1) mem_Collect_eq restrict.simps)

lemma strong_soundnessPK4: ‹G ⊢!K4 p ⟹ transitive; G ⊫!⋆ p›
  using strong_soundnessP[of AxP4 transitive ‹λ_. True› G p]
    soundness_AxP4 transitive_restrict by fast

lemma Ax4_AxP4: ‹Ax4 = AxP4 o lift›
proof
  fix p :: ‹'i fm›
  show ‹Ax4 p = (AxP4 ∘ lift) p›
    unfolding comp_apply using lower_lift
    by (smt (verit, best) Ax4.simps AxP4.simps lift.simps(1, 5-6) lower.simps(5-6))
qed

abbreviation validPK4 (‹_ ⊫!K4 _› [50, 50] 50) where
  ‹G ⊫!K4 p ≡ transitive; G ⊫! p›

lemma strong_completenessPK4:
  assumes ‹G ⊫!K4 p›
  shows ‹G ⊢!K4 p›
  using strong_completenessPB assms strong_completenessK4 unfolding Ax4_AxP4 .

theorem mainPK4: ‹G ⊫!K4 p ⟷ G ⊢!K4 p›
  using strong_soundnessPK4[of G p] strong_completenessPK4[of G p] by fast

corollary ‹G ⊫!K4 p ⟹ transitive; G ⊫!⋆ p›
  using strong_soundnessPK4[of G p] strong_completenessPK4[of G p] by fast

section ‹System PAL + K5›

inductive AxP5 :: ‹'i pfm ⇒ bool› where
  ‹AxP5 (L! i p ⟶! K! i (L! i p))›

abbreviation SystemPK5 (‹_ ⊢!K5 _› [50, 50] 50) where
  ‹G ⊢!K5 p ≡ AxP5; (λ_. True); G ⊢! p›

lemma soundness_AxP5: ‹AxP5 p ⟹ Euclidean M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  by (induct p rule: AxP5.induct) (unfold Euclidean_def psemantics.simps, blast)

lemma Euclidean_restrict: ‹Euclidean M ⟹ Euclidean (M[r!])›
  unfolding Euclidean_def by auto

lemma strong_soundnessPK5: ‹G ⊢!K5 p ⟹ Euclidean; G ⊫!⋆ p›
  using strong_soundnessP[of AxP5 Euclidean ‹λ_. True› G p]
    soundness_AxP5 Euclidean_restrict by fast

lemma Ax5_AxP5: ‹Ax5 = AxP5 o lift›
proof
  fix p :: ‹'i fm›
  show ‹Ax5 p = (AxP5 ∘ lift) p›
    unfolding comp_apply using lower_lift
    by (smt (verit, best) Ax5.simps AxP5.simps lift.simps(1, 5-6) lower.simps(5-6))
qed

abbreviation validPK5 (‹_ ⊫!K5 _› [50, 50] 50) where
  ‹G ⊫!K5 p ≡ Euclidean; G ⊫! p›

lemma strong_completenessPK5:
  assumes ‹G ⊫!K5 p›
  shows ‹G ⊢!K5 p›
  using strong_completenessPB assms strong_completenessK5 unfolding Ax5_AxP5 .

theorem mainPK5: ‹G ⊫!K5 p ⟷ G ⊢!K5 p›
  using strong_soundnessPK5[of G p] strong_completenessPK5[of G p] by fast

corollary ‹G ⊫!K5 p ⟹ Euclidean; G ⊫!⋆ p›
  using strong_soundnessPK5[of G p] strong_completenessPK5[of G p] by fast

section ‹System PAL + S4›

abbreviation SystemPS4 (‹_ ⊢!S4 _› [50, 50] 50) where
  ‹G ⊢!S4 p ≡ AxPT ⊕ AxP4; (λ_. True); G ⊢! p›

lemma soundness_AxPT4: ‹(AxPT ⊕ AxP4) p ⟹ refltrans M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  using soundness_AxPT soundness_AxP4 by fast

lemma refltrans_restrict: ‹refltrans M ⟹ refltrans (M[r!])›
  using reflexive_restrict transitive_restrict by blast

lemma strong_soundnessPS4: ‹G ⊢!S4 p ⟹ refltrans; G ⊫!⋆ p›
  using strong_soundnessP[of ‹AxPT ⊕ AxP4› refltrans ‹λ_. True› G p]
    soundness_AxPT4 refltrans_restrict by fast

lemma AxT4_AxPT4: ‹(AxT ⊕ Ax4) = (AxPT ⊕ AxP4) o lift›
  using AxT_AxPT Ax4_AxP4 unfolding comp_apply by metis

abbreviation validPS4 (‹_ ⊫!S4 _› [50, 50] 50) where
  ‹G ⊫!S4 p ≡ refltrans; G ⊫! p›

theorem strong_completenessPS4:
  assumes ‹G ⊫!S4 p›
  shows ‹G ⊢!S4 p›
  using strong_completenessPB assms strong_completenessS4 unfolding AxT4_AxPT4 .

theorem mainPS4: ‹G ⊫!S4 p ⟷ G ⊢!S4 p›
  using strong_soundnessPS4[of G p] strong_completenessPS4[of G p] by fast

corollary ‹G ⊫!S4 p ⟹ refltrans; G ⊫!⋆ p›
  using strong_soundnessPS4[of G p] strong_completenessPS4[of G p] by fast

section ‹System PAL + S5›

abbreviation SystemPS5 (‹_ ⊢!S5 _› [50, 50] 50) where
  ‹G ⊢!S5 p ≡ AxPT ⊕ AxPB ⊕ AxP4; (λ_. True); G ⊢! p›

abbreviation AxPTB4 :: ‹'i pfm ⇒ bool› where
  ‹AxPTB4 ≡ AxPT ⊕ AxPB ⊕ AxP4›

lemma soundness_AxPTB4: ‹AxPTB4 p ⟹ equivalence M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  using soundness_AxPT soundness_AxPB soundness_AxP4 by fast

lemma equivalence_restrict: ‹equivalence M ⟹ equivalence (M[r!])›
  using reflexive_restrict symmetric_restrict transitive_restrict by blast

lemma strong_soundnessPS5: ‹G ⊢!S5 p ⟹ equivalence; G ⊫!⋆ p›
  using strong_soundnessP[of AxPTB4 equivalence ‹λ_. True› G p]
    soundness_AxPTB4 equivalence_restrict by fast

lemma AxTB4_AxPTB4: ‹AxTB4 = AxPTB4 o lift›
  using AxT_AxPT AxB_AxPB Ax4_AxP4 unfolding comp_apply by metis

abbreviation validPS5 (‹_ ⊫!S5 _› [50, 50] 50) where
  ‹G ⊫!S5 p ≡ equivalence; G ⊫! p›

theorem strong_completenessPS5:
  assumes ‹G ⊫!S5 p›
  shows ‹G ⊢!S5 p›
  using strong_completenessPB assms strong_completenessS5 unfolding AxTB4_AxPTB4 .

theorem mainPS5: ‹G ⊫!S5 p ⟷ G ⊢!S5 p›
  using strong_soundnessPS5[of G p] strong_completenessPS5[of G p] by fast

corollary ‹G ⊫!S5 p ⟹ equivalence; G ⊫!⋆ p›
  using strong_soundnessPS5[of G p] strong_completenessPS5[of G p] by fast

section ‹System PAL + S5'›

abbreviation SystemPS5' (‹_ ⊢!S5'' _› [50, 50] 50) where
  ‹G ⊢!S5' p ≡ AxPT ⊕ AxP5; (λ_. True); G ⊢! p›

abbreviation AxPT5 :: ‹'i pfm ⇒ bool› where
  ‹AxPT5 ≡ AxPT ⊕ AxP5›

lemma soundness_AxPT5: ‹AxPT5 p ⟹ equivalence M ⟹ w ∈ 𝒲 M ⟹ M, w ⊨! p›
  using soundness_AxPT soundness_AxPT soundness_AxP5 symm_trans_Euclid by fast

lemma strong_soundnessPS5': ‹G ⊢!S5' p ⟹ equivalence; G ⊫!⋆ p›
  using strong_soundnessP[of AxPT5 equivalence ‹λ_. True› G p]
    soundness_AxPT5 equivalence_restrict by fast

lemma AxT5_AxPT5: ‹AxT5 = AxPT5 o lift›
  using AxT_AxPT Ax5_AxP5 unfolding comp_apply by metis

theorem strong_completenessPS5':
  assumes ‹G ⊫!S5 p›
  shows ‹G ⊢!S5' p›
  using strong_completenessPB assms strong_completenessS5' unfolding AxT5_AxPT5 .

theorem mainPS5': ‹G ⊫!S5 p ⟷ G ⊢!S5' p›
  using strong_soundnessPS5'[of G p] strong_completenessPS5'[of G p] by fast

end