Theory Epistemic_Logic

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

  This work is a formalization of epistemic logic.
  It includes proofs of soundness and completeness for the axiom system K.
  The completeness proof is based on the textbook "Reasoning About Knowledge"
  by Fagin, Halpern, Moses and Vardi (MIT Press 1995).
  The extensions of system K (T, KB, K4, S4, S5) and their completeness proofs
  are based on the textbook "Modal Logic" by Blackburn, de Rijke and Venema
  (Cambridge University Press 2001).
*)

theory Epistemic_Logic imports Maximal_Consistent_Sets begin

section ‹Syntax›

type_synonym id = string

datatype 'i fm
  = FF ()
  | Pro id
  | Dis 'i fm 'i fm (infixr  60)
  | Con 'i fm 'i fm (infixr  65)
  | Imp 'i fm 'i fm (infixr  55)
  | K 'i 'i fm

abbreviation TT () where
  TT    

abbreviation Neg (¬ _› [70] 70) where
  Neg p  p  

abbreviation L i p  ¬ K i (¬ p)

section ‹Semantics›

record ('i, 'w) frame =
  𝒲 :: 'w set
  𝒦 :: 'i  'w  'w set

record ('i, 'w) kripke =
  ('i, 'w) frame +
  π :: 'w  id  bool

primrec semantics :: ('i, 'w) kripke  'w  'i fm  bool (‹_, _  _› [50, 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)

abbreviation validStar :: (('i, 'w) kripke  bool)  'i fm set  'i fm  bool
  (‹_; _ ⊫⋆ _› [50, 50, 50] 50) where
  P; G ⊫⋆ p  M. P M 
    (w  𝒲 M. (q  G. M, w  q)  M, w  p)

section ‹S5 Axioms›

definition reflexive :: ('i, 'w, 'c) frame_scheme  bool where
  reflexive M  i. w  𝒲 M. w  𝒦 M i w
 
definition symmetric :: ('i, 'w, 'c) frame_scheme  bool where
  symmetric M  i. v  𝒲 M. w  𝒲 M. v  𝒦 M i w  w  𝒦 M i v

definition transitive :: ('i, 'w, 'c) frame_scheme  bool where
  transitive M  i. u  𝒲 M. v  𝒲 M. w  𝒲 M.
    w  𝒦 M i v  u  𝒦 M i w  u  𝒦 M i v

abbreviation refltrans :: ('i, 'w, 'c) frame_scheme  bool where
  refltrans M  reflexive M  transitive M

abbreviation equivalence :: ('i, 'w, 'c) frame_scheme  bool where
  equivalence M  reflexive M  symmetric M  transitive M

definition Euclidean :: ('i, 'w, 'c) frame_scheme  bool where
  Euclidean M  i. u  𝒲 M. v  𝒲 M. w  𝒲 M.
    v  𝒦 M i u  w  𝒦 M i u  w  𝒦 M i v

lemma Imp_intro [intro]: (M, w  p  M, w  q)  M, w  p  q
  by simp

theorem distribution: M, w  K i p  K i (p  q)  K i q
proof
  assume M, w  K i p  K i (p  q)
  then have M, w  K i p M, w  K i (p  q)
    by simp_all
  then have v  𝒲 M  𝒦 M i w. M, v  p v  𝒲 M  𝒦 M i w. M, v  p  q
    by simp_all
  then have v  𝒲 M  𝒦 M i w. M, v  q
    by simp
  then show M, w  K i q
    by simp
qed

theorem generalization:
  fixes M :: ('i, 'w) kripke
  assumes (M :: ('i, 'w) kripke). w  𝒲 M. M, w  p w  𝒲 M
  shows M, w  K i p
proof -
  have w'  𝒲 M  𝒦 M i w. M, w'  p
    using assms by blast
  then show M, w  K i p
    by simp
qed

theorem truth:
  assumes reflexive M w  𝒲 M
  shows M, w  K i p  p
proof
  assume M, w  K i p
  then have v  𝒲 M  𝒦 M i w. M, v  p
    by simp
  moreover have w  𝒦 M i w
    using reflexive M w  𝒲 M unfolding reflexive_def by blast
  ultimately show M, w  p
    using w  𝒲 M by simp
qed

theorem 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 show M, w  K i (K i p)
    by simp
qed

theorem neg_introspection:
  assumes symmetric M transitive M w  𝒲 M
  shows M, w  ¬ K i p  K i (¬ K i p)
proof
  assume M, w  ¬ (K i p)
  then obtain u where u  𝒦 M i w ¬ (M, u  p) u  𝒲 M
    by auto
  moreover have v  𝒲 M  𝒦 M i w. u  𝒲 M  𝒦 M i v
    using u  𝒦 M i w symmetric M transitive M u  𝒲 M w  𝒲 M
    unfolding symmetric_def transitive_def by blast
  ultimately have v  𝒲 M  𝒦 M i w. M, v  ¬ K i p
    by auto
  then show M, w  K i (¬ K i p)
    by simp
qed

section ‹Normal Modal Logic›

primrec eval :: (id  bool)  ('i fm  bool)  'i fm  bool where
  eval _ _  = False
| eval g _ (Pro x) = g x
| eval g h (p  q) = (eval g h p  eval g h q)
| eval g h (p  q) = (eval g h p  eval g h q)
| eval g h (p  q) = (eval g h p  eval g h q)
| eval _ h (K i p) = h (K i p)

abbreviation tautology p  g h. eval g h p

inductive AK :: ('i fm  bool)  'i fm  bool (‹_  _› [50, 50] 50)
  for A :: 'i fm  bool where
    A1: tautology p  A  p
  | A2: A  K i p  K i (p  q)  K i q
  | Ax: A p  A  p
  | R1: A  p  A  p  q  A  q
  | R2: A  p  A  K i p

primrec imply :: 'i fm list  'i fm  'i fm (infixr  56) where
  ([]  q) = q
| (p # ps  q) = (p  ps  q)

abbreviation AK_assms (‹_; _  _› [50, 50, 50] 50) where
  A; G  p  qs. set qs  G  (A  qs  p)

section ‹Soundness›

lemma eval_semantics:
  eval (pi w) (λq. 𝒲 = W, 𝒦 = r, π = pi, w  q) p = (𝒲 = W, 𝒦 = r, π = pi, w  p)
  by (induct p) simp_all

lemma tautology:
  assumes tautology p
  shows M, w  p
proof -
  from assms have eval (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 eval_semantics by fast
  then show M, w  p
    by (metis kripke.cases)
qed

theorem soundness:
  assumes M w p. A p  P M  w  𝒲 M  M, w  p
  shows A  p  P M  w  𝒲 M  M, w  p
  by (induct p arbitrary: w rule: AK.induct) (auto simp: assms tautology)

section ‹Derived rules›

lemma K_A2': A  K i (p  q)  K i p  K i q
proof -
  have A  K i p  K i (p  q)  K i q
    using A2 by fast
  moreover have A  (P  Q  R)  (Q  P  R) for P Q R
    by (simp add: A1)
  ultimately show ?thesis
    using R1 by fast
qed

lemma K_map:
  assumes A  p  q
  shows A  K i p  K i q
proof -
  note A  p  q
  then have A  K i (p  q)
    using R2 by fast
  moreover have A  K i (p  q)  K i p  K i q
    using K_A2' by fast
  ultimately show ?thesis
    using R1 by fast
qed

lemma K_LK: A  (L i (¬ p)  ¬ K i p)
proof -
  have A  (p  ¬ ¬ p)
    by (simp add: A1)
  moreover have A  ((P  Q)  (¬ Q  ¬ P)) for P Q
    using A1 by force
  ultimately show ?thesis
    using K_map R1 by fast
qed

lemma K_imply_head: A  (p # ps  p)
proof -
  have tautology (p # ps  p)
    by (induct ps) simp_all
  then show ?thesis
    using A1 by blast
qed

lemma K_imply_Cons:
  assumes A  ps  q
  shows A  p # ps  q
proof -
  have A  (ps  q  p # ps  q)
    by (simp add: A1)
  with R1 assms show ?thesis .
qed

lemma K_right_mp:
  assumes A  ps  p A  ps  (p  q)
  shows A  ps  q
proof -
  have tautology (ps  p  ps  (p  q)  ps  q)
    by (induct ps) simp_all
  with A1 have A  ps  p  ps  (p  q)  ps  q .
  then show ?thesis
    using assms R1 by blast
qed

lemma tautology_imply_superset:
  assumes set ps  set qs
  shows tautology (ps  r  qs  r)
proof (rule ccontr)
  assume ¬ tautology (ps  r  qs  r)
  then obtain g h where ¬ eval g h (ps  r  qs  r)
    by blast
  then have eval g h (ps  r) ¬ eval g h (qs  r)
    by simp_all
  then consider (np) p  set ps. ¬ eval g h p | (r) p  set ps. eval g h p eval g h r
    by (induct ps) auto
  then show False
  proof cases
    case np
    then have p  set qs. ¬ eval g h p
      using set ps  set qs by blast
    then have eval g h (qs  r)
      by (induct qs) simp_all
    then show ?thesis
      using ¬ eval g h (qs  r) by blast
  next
    case r
    then have eval g h (qs  r)
      by (induct qs) simp_all
    then show ?thesis
      using ¬ eval g h (qs  r) by blast
  qed
qed

lemma K_imply_weaken:
  assumes A  ps  q set ps  set ps'
  shows A  ps'  q
proof -
  have tautology (ps  q  ps'  q)
    using set ps  set ps' tautology_imply_superset by blast
  then have A  ps  q  ps'  q
    using A1 by blast
  then show ?thesis
    using A  ps  q R1 by blast
qed

lemma imply_append: (ps @ ps'  q) = (ps  ps'  q)
  by (induct ps) simp_all

lemma K_ImpI:
  assumes A  p # G  q
  shows A  G  (p  q)
proof -
  have set (p # G)  set (G @ [p])
    by simp
  then have A  G @ [p]  q
    using assms K_imply_weaken by blast
  then have A  G  [p]  q
    using imply_append by metis
  then show ?thesis
    by simp
qed

lemma K_Boole:
  assumes A  (¬ p) # G  
  shows A  G  p
proof -
  have A  G  ¬ ¬ p
    using assms K_ImpI by blast
  moreover have tautology (G  ¬ ¬ p  G  p)
    by (induct G) simp_all
  then have A  (G  ¬ ¬ p  G  p)
    using A1 by blast
  ultimately show ?thesis
    using R1 by blast
qed

lemma K_DisE:
  assumes A  p # G  r A  q # G  r A  G  p  q
  shows A  G  r
proof -
  have tautology (p # G  r  q # G  r  G  p  q  G  r)
    by (induct G) auto
  then have A  p # G  r  q # G  r  G  p  q  G  r
    using A1 by blast
  then show ?thesis
    using assms R1 by blast
qed

lemma K_mp: A  p # (p  q) # G  q
  by (meson K_imply_head K_imply_weaken K_right_mp set_subset_Cons)

lemma K_swap:
  assumes A  p # q # G  r
  shows A  q # p # G  r
  using assms K_ImpI by (metis imply.simps(1-2))

lemma K_DisL:
  assumes A  p # ps  q A  p' # ps  q
  shows A  (p  p') # ps  q
proof -
  have A  p # (p  p') # ps  q A  p' # (p  p') # ps  q
    using assms K_swap K_imply_Cons by blast+
  moreover have A  (p  p') # ps  p  p'
    using K_imply_head by blast
  ultimately show ?thesis
    using K_DisE by blast
qed

lemma K_distrib_K_imp:
  assumes A  K i (G  q)
  shows A  map (K i) G  K i q
proof -
  have A  (K i (G  q)  map (K i) G  K i q)
  proof (induct G)
    case Nil
    then show ?case
      by (simp add: A1)
  next
    case (Cons a G)
    have A  K i a  K i (a # G  q)  K i (G  q)
      by (simp add: A2)
    moreover have
      A  ((K i a  K i (a # G  q)  K i (G  q)) 
        (K i (G  q)  map (K i) G  K i q) 
        (K i a  K i (a # G  q)  map (K i) G  K i q))
      by (simp add: A1)
    ultimately have A  K i a  K i (a # G  q)  map (K i) G  K i q
      using Cons R1 by blast
    moreover have
      A  ((K i a  K i (a # G  q)  map (K i) G  K i q) 
        (K i (a # G  q)  K i a  map (K i) G  K i q))
      by (simp add: A1)
    ultimately have A  (K i (a # G  q)  K i a  map (K i) G  K i q)
      using R1 by blast
    then show ?case
      by simp
  qed
  then show ?thesis
    using assms R1 by blast
qed

lemma K_trans: A  (p  q)  (q  r)  p  r
  by (auto intro: A1)

lemma K_L_dual: A  ¬ L i (¬ p)  K i p
proof -
  have A  K i p  K i p A  ¬ ¬ p  p
    by (auto intro: A1)
  then have A  K i (¬ ¬ p)  K i p
    by (auto intro: K_map)
  moreover have A  (P  Q)  (¬ ¬ P  Q) for P Q
    by (auto intro: A1)
  ultimately show A  ¬ ¬ K i (¬ ¬ p)  K i p
    by (auto intro: R1)
qed

section ‹Strong Soundness›

corollary soundness_imply:
  assumes M w p. A p  P M  w  𝒲 M  M, w  p
  shows A  ps  p  P; set ps ⊫⋆ p
proof (induct ps arbitrary: p)
  case Nil
  then show ?case
    using soundness[of A P p] assms by simp
next
  case (Cons a ps)
  then show ?case
    using K_ImpI by fastforce
qed

theorem strong_soundness:
  assumes M w p. A p  P M  w  𝒲 M  M, w  p
  shows A; G  p  P; G ⊫⋆ p
proof safe
  fix qs w and M :: ('a, 'b) kripke
  assume A  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_imply[of A P qs p] assms by blast
qed

section ‹Completeness›

subsection ‹Consistent sets›

definition consistent :: ('i fm  bool)  'i fm set  bool where
  consistent A S  ¬ (A; S  )

lemma inconsistent_subset:
  assumes consistent A V ¬ consistent A ({p}  V)
  obtains V' where set V'  V A  p # V'  
proof -
  obtain V' where V': set V'  ({p}  V) p  set V' A  V'  
    using assms unfolding consistent_def by blast
  then have *: A  p # V'  
    using K_imply_Cons by blast

  let ?S = removeAll p V'
  have set (p # V')  set (p # ?S)
    by auto
  then have A  p # ?S  
    using * K_imply_weaken by blast
  moreover have set ?S  V
    using V'(1) by (metis Diff_subset_conv set_removeAll)
  ultimately show ?thesis
    using that by blast
qed

lemma consistent_consequent:
  assumes consistent A V p  V A  p  q
  shows consistent A ({q}  V)
proof -
  have V'. set V'  V  ¬ (A  p # V'  )
    using consistent A V p  V unfolding consistent_def
    by (metis insert_subset list.simps(15))
  then have V'. set V'  V  ¬ (A  q # V'  )
    using A  (p  q) K_imply_head K_right_mp by (metis imply.simps(1-2))
  then show ?thesis
    using consistent A V inconsistent_subset by metis
qed

lemma consistent_consequent':
  assumes consistent A V p  V tautology (p  q)
  shows consistent A ({q}  V)
  using assms consistent_consequent A1 by blast

lemma consistent_disjuncts:
  assumes consistent A V (p  q)  V
  shows consistent A ({p}  V)  consistent A ({q}  V)
proof (rule ccontr)
  assume ¬ ?thesis
  then have ¬ consistent A ({p}  V) ¬ consistent A ({q}  V)
    by blast+

  then obtain S' T' where
    S': set S'  V A  p # S'   and
    T': set T'  V A  q # T'  
    using consistent A V inconsistent_subset by metis

  from S' have p: A  p # S' @ T'  
    by (metis K_imply_weaken Un_upper1 append_Cons set_append)
  moreover from T' have q: A  q # S' @ T'  
    by (metis K_imply_head K_right_mp R1 imply.simps(2) imply_append)
  ultimately have A  (p  q) # S' @ T'  
    using K_DisL by blast
  then have A  S' @ T'  
    using S'(1) T'(1) p q consistent A V (p  q)  V unfolding consistent_def
    by (metis Un_subset_iff insert_subset list.simps(15) set_append)
  moreover have set (S' @ T')  V
    by (simp add: S'(1) T'(1))
  ultimately show False
    using consistent A V unfolding consistent_def by blast
qed

lemma exists_finite_inconsistent:
  assumes ¬ consistent A ({¬ p}  V)
  obtains W where {¬ p}  W  {¬ p}  V (¬ p)  W finite W ¬ consistent A ({¬ p}  W)
proof -
  obtain W' where W': set W'  {¬ p}  V A  W'  
    using assms unfolding consistent_def by blast
  let ?S = removeAll (¬ p) W'
  have ¬ consistent A ({¬ p}  set ?S)
    unfolding consistent_def using W'(2) by auto
  moreover have finite (set ?S)
    by blast
  moreover have {¬ p}  set ?S  {¬ p}  V
    using W'(1) by auto
  moreover have (¬ p)  set ?S
    by simp
  ultimately show ?thesis
    by (meson that)
qed

lemma inconsistent_imply:
  assumes ¬ consistent A ({¬ p}  set G)
  shows A  G  p
  using assms K_Boole K_imply_weaken unfolding consistent_def
  by (metis insert_is_Un list.simps(15))

subsection ‹Maximal consistent sets›

lemma fm_any_size: p :: 'i fm. size p = n
proof (induct n)
  case 0
  then show ?case
    using fm.size(7) by blast
next
  case (Suc n)
  then show ?case
    by (metis add.commute add_0 add_Suc_right fm.size(12))
qed

lemma infinite_UNIV_fm: infinite (UNIV :: 'i fm set)
  using fm_any_size by (metis (full_types) finite_imageI infinite_UNIV_nat surj_def)

interpretation MCS consistent A for A :: 'i fm  bool
proof
  show infinite (UNIV :: 'i fm set)
    using infinite_UNIV_fm .
next
  fix S S'
  assume consistent A S S'  S
  then show consistent A S'
    unfolding consistent_def by simp
next
  fix S
  assume ¬ consistent A S
  then show S'  S. finite S'  ¬ consistent A S'
    unfolding consistent_def by blast
qed

theorem deriv_in_maximal:
  assumes consistent A V maximal A V A  p
  shows p  V
  using assms R1 inconsistent_subset unfolding consistent_def maximal_def
  by (metis imply.simps(2))

theorem exactly_one_in_maximal:
  assumes consistent A V maximal A V
  shows p  V  (¬ p)  V
proof
  assume p  V
  then show (¬ p)  V
    using assms K_mp unfolding consistent_def maximal_def
    by (metis empty_subsetI insert_subset list.set(1) list.simps(15))
next
  assume (¬ p)  V
  have A  (p  ¬ p)
    by (simp add: A1)
  then have (p  ¬ p)  V
    using assms deriv_in_maximal by blast
  then have consistent A ({p}  V)  consistent A ({¬ p}  V)
    using assms consistent_disjuncts by blast
  then show p  V
    using maximal A V (¬ p)  V unfolding maximal_def by blast
qed

theorem consequent_in_maximal:
  assumes consistent A V maximal A V p  V (p  q)  V
  shows q  V
proof -
  have V'. set V'  V  ¬ (A  p # (p  q) # V'  )
    using consistent A V p  V (p  q)  V unfolding consistent_def
    by (metis insert_subset list.simps(15))
  then have V'. set V'  V  ¬ (A  q # V'  )
    by (meson K_mp K_ImpI K_imply_weaken K_right_mp set_subset_Cons)
  then have consistent A ({q}  V)
    using consistent A V inconsistent_subset by metis
  then show ?thesis
    using maximal A V unfolding maximal_def by fast
qed

theorem ax_in_maximal:
  assumes consistent A V maximal A V A p
  shows p  V
  using assms deriv_in_maximal Ax by blast

theorem mcs_properties:
  assumes consistent A V and maximal A V
  shows A  p  p  V
    and p  V  (¬ p)  V
    and p  V  (p  q)  V  q  V
  using assms deriv_in_maximal exactly_one_in_maximal consequent_in_maximal by blast+

lemma maximal_extension:
  fixes V :: 'i fm set
  assumes consistent A V
  obtains W where V  W consistent A W maximal A W
proof -
  let ?W = Extend A V
  have V  ?W
    using Extend_subset by blast
  moreover have consistent A ?W
    using assms consistent_Extend by blast
  moreover have maximal A ?W
    using assms maximal_Extend by blast
  ultimately show ?thesis
    using that by blast
qed

subsection ‹Canonical model›

abbreviation pi :: 'i fm set  id  bool where
  pi V x  Pro x  V

abbreviation known :: 'i fm set  'i  'i fm set where
  known V i  {p. K i p  V}

abbreviation reach :: ('i fm  bool)  'i  'i fm set  'i fm set set where
  reach A i V  {W. known V i  W}

abbreviation mcss :: ('i fm  bool)  'i fm set set where
  mcss A  {W. consistent A W  maximal A W}

abbreviation canonical :: ('i fm  bool)  ('i, 'i fm set) kripke where
  canonical A  𝒲 = mcss A, 𝒦 = reach A, π = pi

lemma truth_lemma:
  fixes p :: 'i fm
  assumes consistent A V and maximal A V
  shows p  V  canonical A, V  p
  using assms
proof (induct p arbitrary: V)
  case FF
  then show ?case
  proof safe
    assume   V
    then have False
      using consistent A V K_imply_head unfolding consistent_def
      by (metis bot.extremum insert_subset list.set(1) list.simps(15))
    then show canonical A, V   ..
  next
    assume canonical A, V  
    then show   V
      by simp
  qed
next
  case (Pro x)
  then show ?case
    by simp
next
  case (Dis p q)
  then show ?case
  proof safe
    assume (p  q)  V
    then have consistent A ({p}  V)  consistent A ({q}  V)
      using consistent A V consistent_disjuncts by blast
    then have p  V  q  V
      using maximal A V unfolding maximal_def by fast
    then show canonical A, V  (p  q)
      using Dis by simp
  next
    assume canonical A, V  (p  q)
    then consider canonical A, V  p | canonical A, V  q
      by auto
    then have p  V  q  V
      using Dis by auto
    moreover have A  p  p  q A  q  p  q
      by (auto simp: A1)
    ultimately show (p  q)  V
      using Dis.prems deriv_in_maximal consequent_in_maximal by blast
  qed
next
  case (Con p q)
  then show ?case
  proof safe
    assume (p  q)  V
    then have consistent A ({p}  V) consistent A ({q}  V)
      using consistent A V consistent_consequent' by fastforce+
    then have p  V q  V
      using maximal A V unfolding maximal_def by fast+
    then show canonical A, V  (p  q)
      using Con by simp
  next
    assume canonical A, V  (p  q)
    then have canonical A, V  p canonical A, V  q
      by auto
    then have p  V q  V
      using Con by auto
    moreover have A  p  q  p  q
      by (auto simp: A1)
    ultimately show (p  q)  V
      using Con.prems deriv_in_maximal consequent_in_maximal by blast
  qed
next
  case (Imp p q)
  then show ?case
  proof safe
    assume (p  q)  V
    then have consistent A ({¬ p  q}  V)
      using consistent A V consistent_consequent' by fastforce
    then have consistent A ({¬ p}  V)  consistent A ({q}  V)
      using consistent A V maximal A V consistent_disjuncts unfolding maximal_def by blast
    then have (¬ p)  V  q  V
      using maximal A V unfolding maximal_def by fast
    then have p  V  q  V
      using Imp.prems exactly_one_in_maximal by blast
    then show canonical A, V  (p  q)
      using Imp by simp
  next
    assume canonical A, V  (p  q)
    then consider ¬ canonical A, V  p | canonical A, V  q
      by auto
    then have p  V  q  V
      using Imp by auto
    then have (¬ p)  V  q  V
      using Imp.prems exactly_one_in_maximal by blast
    moreover have A  ¬ p  p  q A  q  p  q
      by (auto simp: A1)
    ultimately show (p  q)  V
      using Imp.prems deriv_in_maximal consequent_in_maximal by blast
  qed
next
  case (K i p)
  then show ?case
  proof safe
    assume K i p  V
    then show canonical A, V  K i p
      using K.hyps by auto
  next
    assume canonical A, V  K i p

    have ¬ consistent A ({¬ p}  known V i)
    proof
      assume consistent A ({¬ p}  known V i)
      then obtain W where W: {¬ p}  known V i  W consistent A W maximal A W
        using consistent A V maximal_extension by blast
      then have canonical A, W  ¬ p
        using K consistent A V exactly_one_in_maximal by auto
      moreover have W  reach A i V W  mcss A
        using W by simp_all
      ultimately have canonical A, V  ¬ K i p
        by auto
      then show False
        using canonical A, V  K i p by auto
    qed

    then obtain W where W:
      {¬ p}  W  {¬ p}  known V i (¬ p)  W finite W ¬ consistent A ({¬ p}  W)
      using exists_finite_inconsistent by metis

    obtain L where L: set L = W
      using finite W finite_list by blast

    then have A  L  p
      using W(4) inconsistent_imply by blast
    then have A  K i (L  p)
      using R2 by fast
    then have A  map (K i) L  K i p
      using K_distrib_K_imp by fast
    then have (map (K i) L  K i p)  V
      using deriv_in_maximal K.prems(1, 2) by blast
    then show K i p  V
      using L W(1-2)
    proof (induct L arbitrary: W)
      case (Cons a L)
      then have K i a  V
        by auto
      then have (map (K i) L  K i p)  V
        using Cons(2) consistent A V maximal A V consequent_in_maximal by auto
      then show ?case
        using Cons by auto
    qed simp
  qed
qed

lemma canonical_model:
  assumes consistent A S and p  S
  defines V  Extend A S and M  canonical A
  shows M, V  p and consistent A V and maximal A V
proof -
  have consistent A V
    using consistent A S unfolding V_def using consistent_Extend by blast
  have maximal A V
    unfolding V_def using maximal_Extend by blast
  { fix x
    assume x  S
    then have x  V
      unfolding V_def using Extend_subset by blast
    then have M, V  x
      unfolding M_def using truth_lemma consistent A V maximal A V by blast }
  then show M, V  p
    using p  S by blast+
  show consistent A V maximal A V
    by fact+
qed

subsection ‹Completeness›

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

theorem strong_completeness:
  assumes P; G  p and P (canonical A)
  shows A; G  p
proof (rule ccontr)
  assume qs. set qs  G  (A  qs  p)
  then have *: qs. set qs  G  ¬ (A  (¬ p) # qs  )
    using K_Boole by blast

  let ?S = {¬ p}  G
  let ?V = Extend A ?S
  let ?M = canonical A

  have consistent A ?S
    using * by (metis K_imply_Cons consistent_def inconsistent_subset)
  then have ?M, ?V  (¬ p) q  G. ?M, ?V  q
    using canonical_model by fastforce+
  moreover have ?V  mcss A
    using consistent A ?S consistent_Extend maximal_Extend by blast
  ultimately have ?M, ?V  p
    using assms by simp
  then show False
    using ?M, ?V  (¬ p) by simp
qed

corollary completeness:
  assumes P; {}  p and P (canonical A)
  shows A  p
  using assms strong_completeness[where G={}] by simp

corollary completenessA:
  assumes (λ_. True); {}  p
  shows A  p
  using assms completeness by blast

section ‹System K›

abbreviation SystemK (‹_ K _› [50] 50) where
  G K p  (λ_. False); G  p

lemma strong_soundnessK: G K p  P; G ⊫⋆ p
  using strong_soundness[of λ_. False λ_. True] by fast

abbreviation validK (‹_ K _› [50, 50] 50) where
  G K p  (λ_. True); G  p

lemma strong_completenessK: G K p  G K p
  using strong_completeness[of λ_. True] by blast

theorem mainK: G K p  G K p
  using strong_soundnessK[of G p] strong_completenessK[of G p] by fast

corollary G K p  (λ_. True); G ⊫⋆ p
  using strong_soundnessK[of G p] strong_completenessK[of G p] by fast

section ‹System T›

text ‹Also known as System M›

inductive AxT :: 'i fm  bool where
  AxT (K i p  p)

abbreviation SystemT (‹_ T _› [50, 50] 50) where
  G T p  AxT; G  p

lemma soundness_AxT: AxT p  reflexive M  w  𝒲 M  M, w  p
  by (induct p rule: AxT.induct) (meson truth)

lemma strong_soundnessT: G T p  reflexive; G ⊫⋆ p
  using strong_soundness soundness_AxT .

lemma AxT_reflexive:
  assumes AxT  A and consistent A V and maximal A V
  shows V  reach A i V
proof -
  have (K i p  p)  V for p
    using assms ax_in_maximal AxT.intros by fast
  then have p  V if K i p  V for p
    using that assms consequent_in_maximal by blast
  then show ?thesis
    using assms by blast
qed

lemma reflexiveT:
  assumes AxT  A
  shows reflexive (canonical A)
  unfolding reflexive_def
proof safe
  fix i V
  assume V  𝒲 (canonical A)
  then have consistent A V maximal A V
    by simp_all
  with AxT_reflexive assms have V  reach A i V .
  then show V  𝒦 (canonical A) i V
    by simp
qed

abbreviation validT (‹_ T _› [50, 50] 50) where
  G T p  reflexive; G  p

lemma strong_completenessT: G T p  G T p
  using strong_completeness reflexiveT by blast

theorem mainT: G T p  G T p
  using strong_soundnessT[of G p] strong_completenessT[of G p] by fast

corollary G T p  reflexive; G ⊫⋆ p
  using strong_soundnessT[of G p] strong_completenessT[of G p] by fast

section ‹System KB›

inductive AxB :: 'i fm  bool where
  AxB (p  K i (L i p))

abbreviation SystemKB (‹_ KB _› [50, 50] 50) where
  G KB p  AxB; G  p

lemma soundness_AxB: AxB p  symmetric M  w  𝒲 M  M, w  p
  unfolding symmetric_def by (induct p rule: AxB.induct) auto

lemma strong_soundnessKB: G KB p  symmetric; G ⊫⋆ p
  using strong_soundness soundness_AxB .

lemma AxB_symmetric':
  assumes AxB  A consistent A V maximal A V consistent A W maximal A W
    and W  reach A i V
  shows V  reach A i W
proof -
  have p. K i p  W  p  V
  proof (safe, rule ccontr)
    fix p
    assume K i p  W p  V
    then have (¬ p)  V
      using assms(2-3) exactly_one_in_maximal by fast
    then have K i (L i (¬ p))  V
      using assms(1-3) ax_in_maximal AxB.intros consequent_in_maximal by fast
    then have L i (¬ p)  W
      using W  reach A i V by fast
    then have (¬ K i p)  W
      using assms(4-5) by (meson K_LK consistent_consequent maximal_def)
    then show False
      using K i p  W assms(4-5) exactly_one_in_maximal by fast
  qed
  then have known W i  V
    by blast
  then show ?thesis
    using assms(2-3) by simp
qed

lemma symmetricKB:
  assumes AxB  A
  shows symmetric (canonical A)
  unfolding symmetric_def
proof (intro allI ballI)
  fix i V W
  assume V  𝒲 (canonical A) W  𝒲 (canonical A)
  then have consistent A V maximal A V consistent A W maximal A W
    by simp_all
  with AxB_symmetric' assms have W  reach A i V  V  reach A i W
    by metis
  then show (W  𝒦 (canonical A) i V) = (V  𝒦 (canonical A) i W)
    by simp
qed

abbreviation validKB (‹_ KB _› [50, 50] 50) where
  G KB p  symmetric; G  p

lemma strong_completenessKB: G KB p  G KB p
  using strong_completeness symmetricKB by blast

theorem mainKB: G KB p  G KB p
  using strong_soundnessKB[of G p] strong_completenessKB[of G p] by fast

corollary G KB p  symmetric; G ⊫⋆ p
  using strong_soundnessKB[of G p] strong_completenessKB[of G p] by fast

section ‹System K4›

inductive Ax4 :: 'i fm  bool where
  Ax4 (K i p  K i (K i p))

abbreviation SystemK4 (‹_ K4 _› [50, 50] 50) where
  G K4 p  Ax4; G  p

lemma soundness_Ax4: Ax4 p  transitive M  w  𝒲 M  M, w  p
  by (induct p rule: Ax4.induct) (meson pos_introspection)

lemma strong_soundnessK4: G K4 p  transitive; G ⊫⋆ p
  using strong_soundness soundness_Ax4 .

lemma Ax4_transitive:
  assumes Ax4  A consistent A V maximal A V
    and W  reach A i V U  reach A i W
  shows U  reach A i V
proof -
  have (K i p  K i (K i p))  V for p
    using assms(1-3) ax_in_maximal Ax4.intros by fast
  then have K i (K i p)  V if K i p  V for p
    using that assms(2-3) consequent_in_maximal by blast
  then show ?thesis
    using assms(4-5) by blast
qed

lemma transitiveK4:
  assumes Ax4  A
  shows transitive (canonical A)
  unfolding transitive_def
proof safe
  fix i U V W
  assume V  𝒲 (canonical A)
  then have consistent A V maximal A V
    by simp_all
  moreover assume
    W  𝒦 (canonical A) i V
    U  𝒦 (canonical A) i W
  ultimately have U  reach A i V
    using Ax4_transitive assms by simp
  then show U  𝒦 (canonical A) i V
    by simp
qed

abbreviation validK4 (‹_ K4 _› [50, 50] 50) where
  G K4 p  transitive; G  p

lemma strong_completenessK4: G K4 p  G K4 p
  using strong_completeness transitiveK4 by blast

theorem mainK4: G K4 p  G K4 p
  using strong_soundnessK4[of G p] strong_completenessK4[of G p] by fast

corollary G K4 p  transitive; G ⊫⋆ p
  using strong_soundnessK4[of G p] strong_completenessK4[of G p] by fast

section ‹System K5›

inductive Ax5 :: 'i fm  bool where
  Ax5 (L i p  K i (L i p))

abbreviation SystemK5 (‹_ K5 _› [50, 50] 50) where
  G K5 p  Ax5; G  p

lemma soundness_Ax5: Ax5 p  Euclidean M  w  𝒲 M  M, w  p
  by (induct p rule: Ax5.induct) (unfold Euclidean_def semantics.simps, blast)

lemma strong_soundnessK5: G K5 p  Euclidean; G ⊫⋆ p
  using strong_soundness soundness_Ax5 .

lemma Ax5_Euclidean:
  assumes Ax5  A
    consistent A U maximal A U
    consistent A V maximal A V
    consistent A W maximal A W
    and V  reach A i U W  reach A i U
  shows W  reach A i V
  using assms
proof -
  { fix p
    assume K i p  V p  W
    then have (¬ p)  W
      using assms(6-7) exactly_one_in_maximal by fast
    then have L i (¬ p)  U
      using assms(2-3, 6-7, 9) exactly_one_in_maximal by blast
    then have K i (L i (¬ p))  U
      using assms(1-3) ax_in_maximal Ax5.intros consequent_in_maximal by fast
    then have L i (¬ p)  V
      using assms(8) by blast
    then have ¬ K i p  V
      using assms(4-5) K_LK consequent_in_maximal deriv_in_maximal by fast
    then have False
      using assms(4-5) K i p  V exactly_one_in_maximal by fast
  }
  then show ?thesis
    by blast
qed

lemma EuclideanK5:
  assumes Ax5  A
  shows Euclidean (canonical A)
  unfolding Euclidean_def
proof safe
  fix i U V W
  assume U  𝒲 (canonical A) V  𝒲 (canonical A) W  𝒲 (canonical A)
  then have
    consistent A U maximal A U
    consistent A V maximal A V
    consistent A W maximal A W
    by simp_all
  moreover assume
    V  𝒦 (canonical A) i U
    W  𝒦 (canonical A) i U
  ultimately have W  reach A i V
    using Ax5_Euclidean assms by simp
  then show W  𝒦 (canonical A) i V
    by simp
qed

abbreviation validK5 (‹_ K5 _› [50, 50] 50) where
  G K5 p  Euclidean; G  p

lemma strong_completenessK5: G K5 p  G K5 p
  using strong_completeness EuclideanK5 by blast

theorem mainK5: G K5 p  G K5 p
  using strong_soundnessK5[of G p] strong_completenessK5[of G p] by fast

corollary G K5 p  Euclidean; G ⊫⋆ p
  using strong_soundnessK5[of G p] strong_completenessK5[of G p] by fast

section ‹System S4›

abbreviation Or :: ('a  bool)  ('a  bool)  'a  bool (infixl  65) where
  (A  A') p  A p  A' p

abbreviation SystemS4 (‹_ S4 _› [50, 50] 50) where
  G S4 p  AxT  Ax4; G  p

lemma soundness_AxT4: (AxT  Ax4) p  reflexive M  transitive M  w  𝒲 M  M, w  p
  using soundness_AxT soundness_Ax4 by fast

lemma strong_soundnessS4: G S4 p  refltrans; G ⊫⋆ p
  using strong_soundness soundness_AxT4 .

abbreviation validS4 (‹_ S4 _› [50, 50] 50) where
  G S4 p  refltrans; G  p

lemma strong_completenessS4: G S4 p  G S4 p
  using strong_completeness[of refltrans] reflexiveT[of AxT  Ax4] transitiveK4[of AxT  Ax4]
  by blast

theorem mainS4: G S4 p  G S4 p
  using strong_soundnessS4[of G p] strong_completenessS4[of G p] by fast

corollary G S4 p  refltrans; G ⊫⋆ p
  using strong_soundnessS4[of G p] strong_completenessS4[of G p] by fast

section ‹System S5›

subsection ‹T + B + 4›

abbreviation SystemS5 (‹_ S5 _› [50, 50] 50) where
  G S5 p  AxT  AxB  Ax4; G  p

abbreviation AxTB4 :: 'i fm  bool where
  AxTB4  AxT  AxB  Ax4

lemma soundness_AxTB4: AxTB4 p  equivalence M  w  𝒲 M  M, w  p
  using soundness_AxT soundness_AxB soundness_Ax4 by fast

lemma strong_soundnessS5: G S5 p  equivalence; G ⊫⋆ p
  using strong_soundness soundness_AxTB4 .

abbreviation validS5 (‹_ S5 _› [50, 50] 50) where
  G S5 p  equivalence; G  p

lemma strong_completenessS5: G S5 p  G S5 p
  using strong_completeness[of equivalence]
    reflexiveT[of AxTB4] symmetricKB[of AxTB4] transitiveK4[of AxTB4]
  by blast

theorem mainS5: G S5 p  G S5 p
  using strong_soundnessS5[of G p] strong_completenessS5[of G p] by fast

corollary G S5 p  equivalence; G ⊫⋆ p
  using strong_soundnessS5[of G p] strong_completenessS5[of G p] by fast

subsection ‹T + 5›

abbreviation SystemS5' (‹_ S5'' _› [50, 50] 50) where
  G S5' p  AxT  Ax5; G  p

abbreviation AxT5 :: 'i fm  bool where
  AxT5  AxT  Ax5

lemma symm_trans_Euclid: symmetric M  transitive M  Euclidean M
  unfolding symmetric_def transitive_def Euclidean_def by blast

lemma soundness_AxT5: AxT5 p  equivalence M  w  𝒲 M  M, w  p
  using soundness_AxT[of p M w] soundness_Ax5[of p M w] symm_trans_Euclid by blast

lemma strong_soundnessS5': G S5' p  equivalence; G ⊫⋆ p
  using strong_soundness soundness_AxT5 .

lemma refl_Euclid_equiv: reflexive M  Euclidean M  equivalence M
  unfolding reflexive_def symmetric_def transitive_def Euclidean_def by metis

lemma strong_completenessS5': G S5 p  G S5' p
  using strong_completeness[of equivalence]
    reflexiveT[of AxT5] EuclideanK5[of AxT5] refl_Euclid_equiv by blast

theorem mainS5': G S5 p  G S5' p
  using strong_soundnessS5'[of G p] strong_completenessS5'[of G p] by fast

subsection ‹Equivalence between systems›

subsubsection ‹Axiom 5 from B and 4›

lemma K4_L:
  assumes Ax4  A
  shows A  L i (L i p)  L i p
proof -
  have A  K i (¬ p)  K i (K i (¬ p))
    using assms by (auto intro: Ax Ax4.intros)
  then show ?thesis
    by (meson K_LK K_trans R1)
qed

lemma KB4_5:
  assumes AxB  A Ax4  A
  shows A  L i p  K i (L i p)
proof -
  have A  L i p  K i (L i (L i p))
    using assms by (auto intro: Ax AxB.intros)
  moreover have A  L i (L i p)  L i p
    using assms by (auto intro: K4_L)
  then have A  K i (L i (L i p))  K i (L i p)
    using K_map by fast
  ultimately show ?thesis
    using K_trans R1 by metis
qed

subsubsection ‹Axioms B and 4 from T and 5›

lemma T_L:
  assumes AxT  A
  shows A  p  L i p
proof -
  have A  K i (¬ p)  ¬ p
    using assms by (auto intro: Ax AxT.intros)
  moreover have A  (P  ¬ Q)  Q  ¬ P for P Q
    by (auto intro: A1)
  ultimately show ?thesis
    by (auto intro: R1)
qed

lemma S5'_B:
  assumes AxT  A Ax5  A
  shows A  p  K i (L i p)
proof -
  have A  L i p  K i (L i p)
    using assms(2) by (auto intro: Ax Ax5.intros)
  moreover have A  p  L i p
    using assms(1) by (auto intro: T_L)
  ultimately show ?thesis
    using K_trans R1 by metis
qed

lemma K5_L:
  assumes Ax5  A
  shows A  L i (K i p)  K i p
proof -
  have A  L i (¬ p)  K i (L i (¬ p))
    using assms by (auto intro: Ax Ax5.intros)
  then have A  L i (¬ p)  K i (¬ K i p)
    using K_LK by (metis K_map K_trans R1)
  moreover have A  (P  Q)  ¬ Q  ¬ P for P Q
    by (auto intro: A1)
  ultimately have A  ¬ K i (¬ K i p)  ¬ L i (¬ p)
    using R1 by blast
  then have A  ¬ K i (¬ K i p)  K i p
    using K_L_dual R1 K_trans by metis
  then show ?thesis
    by blast
qed

lemma S5'_4:
  assumes AxT  A Ax5  A
  shows A  K i p  K i (K i p)
proof -
  have A  L i (K i p)  K i (L i (K i p))
    using assms(2) by (auto intro: Ax Ax5.intros)
  moreover have A  K i p  L i (K i p)
    using assms(1) by (auto intro: T_L)
  ultimately have A  K i p  K i (L i (K i p))
    using K_trans R1 by metis
  moreover have A  L i (K i p)  K i p
    using assms(2) K5_L by metis
  then have A  K i (L i (K i p))  K i (K i p)
    using K_map by fast
  ultimately show ?thesis
    using R1 K_trans by metis
qed

lemma S5_S5': AxTB4  p  AxT5  p
proof (induct p rule: AK.induct)
  case (Ax p)
  moreover have AxT5  p if AxT p
    using that AK.Ax by metis
  moreover have AxT5  p if AxB p
    using that S5'_B by (metis (no_types, lifting) AxB.cases predicate1I)
  moreover have AxT5  p if Ax4 p
    using that S5'_4 by (metis (no_types, lifting) Ax4.cases predicate1I)
  ultimately show ?case
    by blast
qed (auto intro: AK.intros)

lemma S5'_S5: AxT5  p  AxTB4  p
proof (induct p rule: AK.induct)
  case (Ax p)
  moreover have AxTB4  p if AxT p
    using that AK.Ax by metis
  moreover have AxTB4  p if Ax5 p
    using that KB4_5 by (metis (no_types, lifting) Ax5.cases predicate1I)
  ultimately show ?case
    by blast
qed (auto intro: AK.intros)

corollary S5_S5'_assms: G S5 p  G S5' p
  using S5_S5' S5'_S5 by blast

section ‹Acknowledgements›

text ‹
The formalization is inspired by Berghofer's formalization of Henkin-style completeness.

   Stefan Berghofer:
  First-Order Logic According to Fitting.
  🌐‹https://www.isa-afp.org/entries/FOL-Fitting.shtml›

end