Theory Abstract_Consistency_Property

(*
  Author: Asta Halkjær Boserup, 2026.

  Inspiration:
  - "A Unifying Principal in Quantification Theory", 1963, Raymond M. Smullyan.
  - "First-Order Logic", 1968, Raymond M. Smullyan.
  - "First-Order Logic and Automated Theorem Proving", 1996, Melvin Fitting.
  - "FOL-Fitting", Stefan Berghofer.
*)

chapter ‹Abstract Consistency Properties›

theory Abstract_Consistency_Property imports
  "HOL-Cardinals.Cardinal_Order_Relation"
begin

section ‹Utility›

lemma Set_Diff_Un: X - (Y  Z) = X - Y - Z
  by blast

lemma infinite_diff_finite: finite A  infinite (- B)  infinite (- (A  B))
  by (metis Compl_Diff_eq double_complement finite_Diff2 sup_commute)

lemma infinite_Diff_fin_Un: infinite (X - Y)  finite Z  infinite (X - (Z  Y))
  by (simp add: Set_Diff_Un Un_commute)

lemma infinite_Diff_subset: infinite (X - A)  B  A  infinite (X - B)
  by (meson Diff_cancel Diff_eq_empty_iff Diff_mono infinite_super)

lemma finite_bound:
  fixes X :: ('a :: size) set
  assumes finite X X  {}
  shows x  X. y  X. size y  size x
  using assms by (induct X rule: finite_induct) force+

lemma infinite_UNIV_size:
  fixes f :: ('a :: size)  'a
  assumes x. size x < size (f x)
  shows infinite (UNIV :: 'a set)
proof
  assume finite (UNIV :: 'a set)
  then obtain x :: 'a where y :: 'a. size y  size x
    using finite_bound by fastforce
  moreover have size x < size (f x)
    using assms .
  ultimately show False
    using leD by blast
qed

lemma infinite_left: finite C  infinite A  |A| ≤o |- B|  |A| ≤o |- (C  B)|
  by (metis (no_types, opaque_lifting) Compl_Diff_eq card_of_infinite_diff_finite card_of_ordLeq_finite
      double_complement ordIso_iff_ordLeq ordLeq_transitive sup_commute)

lemma card_of_infinite_smaller_Union:
  assumes x. |f x| <o |X| infinite X
  shows |x  X. f x| ≤o |X|
  using assms by (metis (full_types) Field_card_of card_of_UNION_ordLeq_infinite
      card_of_well_order_on ordLeq_iff_ordLess_or_ordIso ordLess_or_ordLeq)

context wo_rel
begin

lemma underS_bound: a  underS c  b  underS c  a  under b  b  under a
  by (meson BNF_Least_Fixpoint.underS_Field REFL Refl_under_in in_mono under_ofilter ofilter_linord)

lemma finite_underS_bound:
  assumes finite X X  underS a X  {}
  shows a  X. b  X. b  under a
  using assms
proof (induct X rule: finite_induct)
  case (insert x F)
  then show ?case
  proof (cases F = {})
    case True
    then show ?thesis
      using insert underS_bound by fast
  next
    case False
    then show ?thesis
      using insert underS_bound by (metis TRANS insert_absorb insert_iff insert_subset under_trans)
  qed
qed simp

lemma finite_bound_under:
  assumes finite p p  (a  Field r. f a)
  shows b. p  (a  under b. f a)
  using assms
proof (induct rule: finite_induct)
  case (insert x p)
  then obtain b where p  (a  under b. f a)
    by fast
  moreover obtain b' where x  f b' b'  Field r
    using insert(4) by blast
  then have x  (a  under b'. f a)
    using REFL Refl_under_in by fast
  ultimately have {x}  p  (a  under b. f a)  (a  under b'. f a)
    by fast
  then show ?case
    by (metis SUP_union Un_commute insert_is_Un sup.absorb_iff2 ofilter_linord under_ofilter)
qed simp

lemma underS_trans: a  underS b  b  underS c  a  underS c
  by (meson ANTISYM TRANS underS_underS_trans)

definition is_chain :: ('a  'a set)  bool where
  is_chain f  a  Field r. b  Field r. b  under a  f b  f a

lemma is_chainD: is_chain f  b  under a  x  f b  x  f a
  unfolding is_chain_def by (metis equals0D subsetD under_Field under_empty)

lemma chain_index:
  assumes ch: is_chain f and fin: finite F and ne: Field r  {}
  shows F  (a  Field r. f a)  a  Field r. F  f a
  using fin
proof (induct rule: finite_induct)
  case empty
  then show ?case
    using ne by blast
next
  case (insert x F)
  then have a  Field r. F  f a b  Field r. x  f b F  (x  Field r. f x)
    using ch by simp_all
  then obtain a and b where f: F  f a x  f b and nm: a  Field r b  Field r
    by blast
  have b  under (max2 a b) a  under (max2 a b)
    using nm  by (meson REFL Refl_under_in TRANS max2_greater_among subset_iff under_incl_iff)+
  have x  f (max2 a b)
    using is_chainD ch b  under (max2 a b) f(2) by blast
  moreover have F  f (max2 a b)
    using is_chainD ch a  local.under (max2 a b) f(1) by blast
  ultimately show ?case
    using nm unfolding max2_def by auto
qed

end

section ‹Finite Character›

definition close :: 'a set set  'a set set where
  close C  {S. (S'  C. S  S')}

definition subset_closed :: 'a set set  bool where
  subset_closed C  S'  C. S  S'. S  C

lemma subset_in_close: S  S'  x  S'  C  x  S  close C
  unfolding close_def by blast

lemma close_closed: subset_closed (close C)
  unfolding close_def subset_closed_def by blast

lemma close_subset: C  close C
  unfolding close_def by blast

definition finite_char :: 'a set set  bool where
  finite_char C  S. S  C  (S'  S. finite S'  S'  C)

definition mk_finite_char :: 'a set set  'a set set where
  mk_finite_char C  {S. (S'  S. finite S'  S'  C)}

lemma finite_char: finite_char (mk_finite_char C)
  unfolding finite_char_def mk_finite_char_def by blast

lemma finite_char_closed: finite_char C  subset_closed C
  unfolding finite_char_def subset_closed_def by (meson order_trans)

lemma finite_char_subset: subset_closed C  C  mk_finite_char C
  unfolding mk_finite_char_def subset_closed_def by blast

lemma (in wo_rel) chain_union_closed:
  assumes finite_char C is_chain f a  Field r. f a  C Field r  {}
  shows (a  Field r. f a)  C
  using assms chain_index unfolding finite_char_def by metis

definition maximal :: 'a set set  'a set  bool where
  maximal C S  (S'  C. S  S'  S = S')

section ‹Consistency Properties›

locale Params =
  fixes map_fm :: ('x  'x)  'fm  'fm
    and params_fm :: 'fm  'x set
    and is_param :: 'x  bool
  assumes map_fm_id: map_fm id = id
    and finite_params_fm [simp]: p. finite (params_fm p)
    and map_params_fm: f g p. (x  params_fm p. f x = g x)  map_fm f p = map_fm g p
begin

definition is_subst :: ('x  'x)  bool where
  is_subst f  x. is_param x  is_param (f x)

lemma is_subst_id [intro]: is_subst id
  unfolding is_subst_def by simp

definition mk_alt_consistency :: 'fm set set  'fm set set where
  mk_alt_consistency C  {S. (f. is_subst f  map_fm f ` S  C)}

lemma mk_alt_consistency_subset: C  mk_alt_consistency C
  unfolding mk_alt_consistency_def
proof
  fix x
  assume x  C
  then have map_fm id ` x  C
    using map_fm_id by simp
  then have f. is_subst f  map_fm f ` x  C
    by blast
  then show x  {S. f. is_subst f  map_fm f ` S  C}
    by blast
qed

lemma mk_alt_consistency_closed:
  assumes subset_closed C
  shows subset_closed (mk_alt_consistency C)
  unfolding subset_closed_def mk_alt_consistency_def
proof safe
  fix S S' f
  assume is_subst f map_fm f ` S'  C S  S'
  moreover have map_fm f ` S  map_fm f ` S'
    using S  S' by blast
  moreover have S'  C. S  S'. S  C
    using subset_closed C unfolding subset_closed_def by blast
  ultimately show f. is_subst f  map_fm f ` S  C
    by blast
qed

abbreviation params :: 'fm set  'x set where
  params S  p  S. params_fm p

lemma infinite_params: infinite (U - params B)  infinite (U - params (set ps  B))
  using finite_params_fm by (metis List.finite_set UN_Un finite_UN_I infinite_Diff_fin_Un)

lemma infinite_params_left: 
  assumes infinite A |A| ≤o |U - params S|
  shows |A| ≤o |U - params (set ps  S)|
proof -
  have infinite (U - params S)
    using assms card_of_ordLeq_infinite by blast
  then have |U - params S| =o |U - params (set ps  S)|
    by (simp add: Set_Diff_Un Un_commute card_of_infinite_diff_finite ordIso_symmetric)
  then show ?thesis
    using assms(2) ordLeq_ordIso_trans by blast
qed

definition enough_new :: 'fm set  bool where
  enough_new S  |UNIV :: 'fm set| ≤o |Collect is_param - params S|

lemma enough_new_countable:
  assumes to_nat :: 'fm  nat. inj to_nat infinite (Collect is_param - params S)
  shows enough_new S
  unfolding enough_new_def using assms
  by (meson UNIV_I card_of_ordLeqI infinite_iff_card_of_nat ordLeq_transitive)

lemma enough_new_all_param:
  assumes |UNIV :: 'fm set| ≤o |UNIV - params S| x. is_param x
  shows enough_new S
  unfolding enough_new_def using assms by (simp add: Collect_cong)

end

datatype ('x, 'fm) kind
  = Cond 'fm list  ('fm set set  'fm set  bool)  bool 'fm set  bool
  | Wits 'fm  'x  'fm list

inductive (in Params) satE :: ('x, 'fm) kind  'fm set set  bool where
  satE_Cond [intro!]: (S ps Q. S  C  set ps  S  P ps Q  Q C S)  satE (Cond P H) C
| satE_Wits [intro!]: (S p. S  C  p  S  (x. is_param x  set (W p x)  S  C))  satE (Wits W) C

inductive_cases (in Params) satE_CondE[elim!]: satE (Cond P H) C
inductive_cases (in Params) satE_WitsE[elim!]: satE (Wits W) C

inductive (in Params) satA :: ('x, 'fm) kind  'fm set set  bool where
  satA_Cond [intro!]: (S ps Q. S  C  set ps  S  P ps Q  Q C S)  satA (Cond P H) C
| satA_Wits [intro!]: (S p x. S  C  p  S  x  params S  is_param x  set (W p x)  S  C)  satA (Wits W) C

inductive_cases (in Params) satA_CondE[elim!]: satA (Cond P H) C
inductive_cases (in Params) satA_WitsE[elim!]: satA (Wits W) C

definition (in Params) propE :: ('x, 'fm) kind list  'fm set set  bool where
  propE Ks C  K  set Ks. satE K C

definition (in Params) propA :: ('x, 'fm) kind list  'fm set set  bool where
  propA Ks C  K  set Ks. satA K C

inductive (in Params) satH :: ('x, 'fm) kind  'fm set  bool where
  satH_Cond [intro!]: H S  satH (Cond P H) S
| satH_Wits [intro!]: (p. p  S  (x. is_param x  set (W p x)  S))  satH (Wits W) S

inductive_cases (in Params) satH_CondE[elim!]: satH (Cond P H) C
inductive_cases (in Params) satH_WitsE[elim!]: satH (Wits W) C

definition (in Params) propH :: ('x, 'fm) kind list  'fm set  bool where
  propH Ks S  K  set Ks. satH K S

theorem (in Params) satH_Wits: satE (Wits W) C  S  C  maximal C S  satH (Wits W) S
  unfolding maximal_def by fast

subsection ‹Consistency Kinds›

locale Consistency_Kind = Params map_fm params_fm is_param
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes K :: ('x, 'fm) kind
  assumes respects_close: C. satE K C  satE K (close C)
    and respects_alt: C. satE K C  subset_closed C  satA K (mk_alt_consistency C)
    and respects_fin: C. subset_closed C  satA K C  satA K (mk_finite_char C)
    and hintikka: C S. satE K C  S  C  maximal C S  satH K S

locale Consistency_Kinds = Params map_fm params_fm is_param
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes Ks :: ('x, 'fm) kind list
  assumes all_kinds: K. K  set Ks  Consistency_Kind map_fm params_fm is_param K
begin

lemma satE: K  set Ks  propE Ks C  satE K C
  unfolding propE_def by blast

lemma propE_close: propE Ks C  propE Ks (close C)
  unfolding propE_def using all_kinds Consistency_Kind.respects_close by fast

lemma propE_alt: propE Ks C  subset_closed C  propA Ks (mk_alt_consistency C)
  unfolding propE_def propA_def using all_kinds Consistency_Kind.respects_alt by fast

lemma propE_fin: subset_closed C  propA Ks C  propA Ks (mk_finite_char C)
  unfolding propA_def using all_kinds Consistency_Kind.respects_fin by fast

definition mk_alt_fin :: 'fm set set  'fm set set where
  mk_alt_fin C  mk_finite_char (mk_alt_consistency (close C))

lemma mk_alt_fin_subset_closed: subset_closed (mk_alt_fin C)
  unfolding mk_alt_fin_def using finite_char finite_char_closed by blast

lemma mk_alt_fin_finite_char: finite_char (mk_alt_fin C)
  unfolding mk_alt_fin_def using finite_char by blast

lemma mk_alt_fin_in: S  C  S  mk_alt_fin C
  unfolding mk_alt_fin_def
  by (meson close_closed close_subset finite_char_subset in_mono mk_alt_consistency_closed mk_alt_consistency_subset)

theorem propE: propE Ks C  propA Ks (mk_alt_fin C)
  unfolding mk_alt_fin_def
  by (simp add: propE_alt propE_close propE_fin close_closed mk_alt_consistency_closed)

end

fun (in Params) witness_kinds :: ('x, 'fm) kind list  'fm  'fm set  'fm set where
  witness_kinds [] p S = {}
| witness_kinds (Cond _ _ # Ks) p S = witness_kinds Ks p S
| witness_kinds (Wits W # Ks) p S =
  (let
    rest = witness_kinds Ks p S;
    a = SOME x. x  Collect is_param - params (rest  {p}  S)
   in set (W p a)  rest)

lemma (in Params) witness_kinds_new:
  assumes infinite (UNIV :: 'fm set) infinite (Collect is_param - params S)
  shows infinite (Collect is_param - params (witness_kinds Ks p S  {p}  S))
  using assms
proof (induct Ks p S rule: witness_kinds.induct)
  case (1 p S)
  then show ?case
    by (simp add: infinite_Diff_fin_Un)
next
  case (3 W Ks p S)
  then show ?case
    by (metis (no_types, lifting) infinite_params sup_assoc witness_kinds.simps(3))
qed simp_all

lemma (in Params) witness_kinds:
  assumes inf: infinite (UNIV :: 'fm set) and infinite (Collect is_param - params S) Wits W  set Ks
  shows x. is_param x  set (W p x)  witness_kinds Ks p S
  using assms(2-)
proof (induct Ks p S rule: witness_kinds.induct)
  case (3 W' Ks p S)
  moreover have infinite (Collect is_param - params (witness_kinds Ks p S  {p}  S))
    using inf 3 witness_kinds_new by blast
  then have x. x  Collect is_param - params (witness_kinds Ks p S  {p}  S)
    by (metis equals0I finite.emptyI)
  then obtain x where x:
    (SOME x. x  Collect is_param - params (witness_kinds Ks p S  {p}  S)) = x
    is_param x
    by (metis (mono_tags, lifting) DiffE mem_Collect_eq someI_ex)
  ultimately show ?case
    by (auto simp: Let_def)
qed simp_all

locale Maximal_Consistency = wo_rel |UNIV| :: 'fm rel + Consistency_Kinds map_fm params_fm is_param Ks
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    Ks :: ('x, 'fm) kind list +
  assumes inf_univ: infinite (UNIV :: 'fm set)
begin

lemma Cinfinite_r: Cinfinite |UNIV :: 'fm set|
  by (simp add: cinfinite_def inf_univ)

lemma isLimOrd: isLimOrd
  using Cinfinite_r card_order_infinite_isLimOrd cinfinite_def by blast

lemma aboveS_ne: aboveS a  {}
  by (simp add: isLimOrd isLimOrd_aboveS)

lemma params_left: enough_new S  enough_new (set ps  S)
  unfolding enough_new_def using infinite_params_left inf_univ by blast

definition witness :: 'fm  'fm set  'fm set where
  witness  witness_kinds Ks

definition extendS :: 'fm set set  'fm  'fm set  'fm set where
  extendS C a prev  if ({a}  prev  C) then (witness a prev  {a}  prev) else prev

definition extendL :: 'fm set set  ('fm  'fm set)  'fm  'fm set where
  extendL C rec a  b  underS a. rec b

definition extend :: 'fm set set  'fm set  'fm  'fm set where
  extend C S a  worecZSL S (extendS C) (extendL C) a

lemma adm_woL_extendL: adm_woL (extendL C)
  unfolding extendL_def adm_woL_def by blast

definition Extend :: 'fm set set  'fm set  'fm set where
  Extend C S  a. extend C S a

lemma finite_witness_kinds: finite (witness_kinds Qs p S)
  unfolding witness_def by (induct Qs p S rule: witness_kinds.induct) (simp_all add: Let_def)

lemma finite_witness: finite (witness p S)
  unfolding witness_def using finite_witness_kinds .

lemma finite_witness_kinds_params: finite (params (witness_kinds Qs p S))
  using finite_witness_kinds by simp

lemma finite_witness_params: finite (params (witness p S))
  using finite_witness by simp

lemma extend_zero [simp]: extend C S zero = S
  unfolding extend_def worecZSL_zero[OF adm_woL_extendL] ..

lemma extend_succ [simp]: extend C S (succ a) =
    (if {a}  extend C S a  C then witness a (extend C S a)  {a}  extend C S a else extend C S a)
  unfolding extend_def extendS_def worecZSL_succ[OF adm_woL_extendL aboveS_ne] ..

lemma extend_isLim [simp]:
  assumes isLim a a  zero
  shows extend C S a = (b  underS a. extend C S b)
  unfolding extend_def extendL_def worecZSL_isLim[OF adm_woL_extendL assms] ..

lemma extend_subset: S  extend C S a
proof (induct a rule: well_order_inductZSL)
  case (Lim i)
  then show ?case
    using zero_smallest by (metis Field_card_of SUP_upper2 UNIV_I extend_isLim underS_I)
qed auto

lemma Extend_subset: S  Extend C S
  unfolding Extend_def using extend_subset by fast

lemma extend_underS: b  underS a  extend C S b  extend C S a
proof (induct a rule: well_order_inductZSL)
  case Zero
  then show ?case
    using underS_zero by blast
next
  case (Suc i)
  moreover from this have b = i  b  underS i
    using less_succ by (metis underS_E underS_I)
  ultimately show ?case
    by auto
next
  case (Lim i)
  then show ?case
    by auto
qed

lemma extend_under: b  under a  extend C S b  extend C S a
  using extend_underS supr_greater supr_under
  by (metis emptyE in_Above_under set_eq_subset underS_I under_empty)

lemma params_origin:
  assumes x  params (extend C S a)
  shows x  params S  (b  underS a. x  params (witness b (extend C S b)  {b}))
  using assms
proof (induct a rule: well_order_inductZSL)
  case Zero
  then show ?case
    by simp
next
  case (Suc i)
  then consider
    (here) x  params ({i}  witness i (extend C S i)) |
    (there) x  params (extend C S i)
    using Suc(3) by (fastforce split: if_splits)
  then show ?case
  proof cases
    case here
    then show ?thesis
      using Suc(1) succ_diff succ_in by (metis sup_commute underS_I )
  next
    case there
    then show ?thesis
      using Suc by (metis in_mono underS_subset_under underS_succ)
  next
  qed
next
  case (Lim i)
  then obtain j where j  underS i x  params (extend C S j)
    unfolding extend_def extendL_def worecZSL_isLim[OF adm_woL_extendL Lim(1-2)]
    by blast
  then show ?case
    using Lim underS_trans[of _ j i] by meson
qed

lemma is_chain_extend: is_chain (extend C S)
  by (simp add: extend_under is_chain_def)

lemma extend_in_C_step:
  assumes propA Ks C {a}  extend C S a  C
    and inf: infinite (Collect is_param - params ({a}  extend C S a))
  shows extend C S (succ a)  C
proof -
  have set Qs  set Ks  witness_kinds Qs a (extend C S a)  {a}  extend C S a  C for Qs
  proof (induct Qs)
    case Nil
    then show ?case
      using assms(2) by simp
  next
    case (Cons Q Qs)
    let ?S = extend C S a
    let ?rest = witness_kinds Qs a ?S

    have Q: Q  set Ks
      using Cons.prems by simp

    have *: ?rest  {a}  ?S  C
      using Cons by simp

    show ?case
    proof (cases Q)
      case (Wits W)

      have infinite (Collect is_param - params (?rest  {a}  ?S))
        using finite_witness_kinds_params inf by (metis UN_Un Un_assoc infinite_Diff_fin_Un)
      then have **: x. x  Collect is_param - params (?rest  {a}  ?S)
        by (metis ex_in_conv finite.emptyI)
      then obtain x where x:
        (SOME x. x  Collect is_param - params (?rest  {a}  ?S)) = x
        x  params (?rest  {a}  ?S)
        is_param x
        by (metis (mono_tags, lifting) DiffE mem_Collect_eq someI_ex)

      have a  ?rest  {a}  ?S
        by simp
      then have x. x  params (?rest  {a}  ?S)  is_param x  set (W a x)  ?rest  {a}  ?S  C
        using assms(1) * Q Wits unfolding propA_def Un_assoc by fast
      then have set (W a x)  ?rest  {a}  ?S  C
        using x by fast

      moreover have witness_kinds (Q # Qs) a ?S = set (W a x)  ?rest
        using Cons Wits x by (simp add: Let_def)
      ultimately show ?thesis
        by simp
    next
      case (Cond P)
      then show ?thesis
        using * by simp
    qed
  qed
  then have witness a (extend C S a)  {a}  extend C S a  C
    unfolding witness_def by blast
  then show ?thesis
    unfolding extend_succ using assms(2) by simp
qed

lemma extend_in_C_stop:
  assumes extend C S a  C
    and {a}  extend C S a  C
  shows extend C S (succ a)  C
  using assms extend_succ by auto


lemma infinite_succ_extend:
  assumes S  C enough_new S isSucc p
  shows infinite (Collect is_param - params (extend C S p))
  using assms
proof (induct p rule: well_order_inductZSL)
  case Zero
  then show ?case
    using not_isSucc_zero by blast
next
  case (Suc i)
  then have *: |underS i| <o |UNIV :: 'fm set|
    using card_of_underS by (simp add: Cinfinite_r)

  let ?params = λk. params ({k}  witness k (extend C S k))
  let ?X = k  underS i. ?params k
  have |?X| <o |UNIV :: 'fm set|
  proof (cases finite (underS i))
    case True
    then have finite ?X
      using finite_witness_params by simp
    then show ?thesis
      using Cinfinite_r unfolding cinfinite_def by (simp add: finite_ordLess_infinite)
  next
    case False
    moreover have k. finite (?params k)
      using finite_witness_params by simp
    then have k. |?params k| <o |underS i|
      using False by simp
    ultimately have |?X| ≤o |underS i|
      using card_of_infinite_smaller_Union by fast
    then show ?thesis
      using * ordLeq_ordLess_trans by blast
  qed
  then have |?X| <o |Collect is_param - params S|
    using Suc(4) ordLess_ordLeq_trans unfolding enough_new_def by blast
  moreover have infinite (Collect is_param - params S)
    using Suc(4) Cinfinite_r unfolding cinfinite_def enough_new_def
    by (metis Field_card_of ordLeq_finite_Field)
  ultimately have |Collect is_param - params S - ?X| =o |Collect is_param - params S|
    using card_of_Un_diff_infinite by blast
  moreover from this have infinite (Collect is_param - params S - ?X)
    using infinite (Collect is_param - params S) card_of_ordIso_finite by blast
  moreover have a. a  params (extend C S i)  a  params S  a  ?X
    using params_origin by simp
  then have params (extend C S i)  params S  ?X
    by fast
  ultimately have infinite (Collect is_param - params (extend C S i))
    using infinite_Diff_subset by (metis (no_types, lifting) Set_Diff_Un)
  then show ?case
    using Suc extend_succ inf_univ witness_def witness_kinds_new by presburger
next
  case (Lim i)
  then show ?case
    using isLim_def by blast
qed

lemma extend_in_C:
  assumes propA Ks C finite_char C S  C enough_new S
  shows extend C S a  C
  using assms
proof (induct a rule: well_order_inductZSL)
  case Zero
  then show ?case
    by (simp add: adm_woL_extendL extend_def worecZSL_zero)
next
  case (Suc i)
  have infinite (Collect is_param - params (extend C S (succ i)))
    using infinite_succ_extend aboveS_ne assms(3,4) isSucc_succ by blast
  then have infinite (Collect is_param - params (extend C S i))
    using extend_succ[of C S i]  by (metis UN_Un Un_upper2 infinite_Diff_subset)
  then have infinite (Collect is_param - params ({i}  extend C S i))
    using finite_params_fm  by (simp add: Compl_eq_Diff_UNIV infinite_Diff_fin_Un)
  then show ?case
    using Suc extend_in_C_step extend_in_C_stop succ_in[of i] by blast
next
  case (Lim i)
  show ?case
  proof (rule ccontr)
    assume extend C S i  C
    then obtain S' where S': S'  (a  underS i. extend C S a) S'  C finite S'
      using Lim(5) unfolding finite_char_def extend_def extendL_def worecZSL_isLim[OF adm_woL_extendL Lim(1-2)]
      by blast
    then obtain as where as: S'  (a  as. extend C S a) as  underS i finite as
      by (metis finite_subset_Union finite_subset_image)
    moreover from this(1) have as  {}
      using S' Lim unfolding finite_char_def
      by (metis Union_empty bot.extremum_uniqueI empty_subsetI image_empty)
    ultimately obtain j where a  as. a  under j j  underS i
      using finite_underS_bound by (metis in_mono)
    then have a  as. extend C S a  extend C S j
      using extend_under by fast
    then have S'  extend C S j
      using S' as(1) by blast
    then show False
      using Lim(3-) S'(2) as(2-3) aas. a  under j as  {} j  underS i
      by (meson Order_Relation.underS_Field finite_char_closed subsetD subset_closed_def)
  qed
qed

lemma Extend_in_C:
  assumes propA Ks C finite_char C S  C enough_new S
  shows Extend C S  C
  unfolding Extend_def using assms chain_union_closed is_chain_extend extend_in_C by simp

theorem Extend_maximal:
  assumes subset_closed C
  shows maximal C (Extend C S)
  unfolding maximal_def Extend_def
proof (intro ballI impI)
  fix S'
  assume *: S'  C (x. extend C S x)  S'
  moreover have S'  (x. extend C S x)
  proof (rule ccontr)
    assume ¬ S'  (x. extend C S x)
    then have z. z  S'  z  (x. extend C S x)
      by blast
    then obtain a where a: a  S' a  (x. extend C S x)
      using *(1) by blast
    then have {a}  extend C S a  S'
      using * by blast
    moreover have S  S'. S  C
      using assms S'  C unfolding subset_closed_def by blast
    ultimately have {a}  extend C S a  C
      by blast
    then have a  extend C S (succ a)
      using a by simp
    then show False
      using * a by blast
  qed
  ultimately show (x. extend C S x) = S'
    by simp
qed

definition witnessed :: 'fm set  bool where
  witnessed S  p  S. S'. infinite (Collect is_param - params S')  witness p S'  S

theorem Extend_witnessed:
  assumes propA Ks C finite_char C S  C enough_new S
  shows witnessed (Extend C S)
  unfolding witnessed_def
proof safe
  fix p
  assume p  Extend C S
  then have {p}  extend C S p  Extend C S
    unfolding Extend_def by blast
  moreover have Extend C S  C
    using Extend_in_C assms by blast
  ultimately have {p}  extend C S p  C
    using finite_char C finite_char_closed unfolding subset_closed_def by blast
  moreover have extend C S (succ p)  C
    using assms extend_in_C by blast
  ultimately have witness p (extend C S p)  {p}  extend C S p  C
    unfolding extend_succ by simp
  then have witness p (extend C S p)  {p}  extend C S p  Extend C S
    unfolding Extend_def using extend_succ {p}  extend C S p  C by fastforce
  moreover have infinite (Collect is_param - params (extend C S (succ p)))
    using infinite_succ_extend by (meson aboveS_ne assms(3,4) isSucc_def)
  then have infinite (Collect is_param - params (extend C S p))
    using extend_succ by (metis SUP_union Un_upper2 infinite_Diff_subset)
  ultimately show S'. infinite (Collect is_param - params S')  witness p S'  Extend C S
    by fast
qed

abbreviation mk_mcs :: 'fm set set  'fm set  'fm set where
  mk_mcs C S  Extend (mk_alt_fin C) S

theorem mk_mcs_rmaximal: maximal C (mk_mcs C S)
  using Extend_maximal maximal_def mk_alt_fin_in mk_alt_fin_subset_closed by meson

theorem mk_mcs_witnessed:
  assumes propE Ks C S  C enough_new S
  shows witnessed (mk_mcs C S)
  using assms Extend_witnessed propE mk_alt_fin_finite_char mk_alt_fin_in by blast

section ‹Hintikka Sets›

lemma mk_mcs_hintikka:
  assumes propE Ks C S  C enough_new S
  shows propH Ks (mk_mcs C S)
  unfolding propH_def
proof
  fix K
  assume K: K  set Ks
  show satH K (mk_mcs C S)
  proof (cases K)
    case (Cond P H)
    moreover have maximal (mk_alt_fin C) (mk_mcs C S)
      using Extend_maximal mk_alt_fin_subset_closed by blast
    moreover have propA Ks (mk_alt_fin C)
      using assms(1) propE by blast
    then have mk_mcs C S  mk_alt_fin C
      using assms(2-3) Extend_in_C mk_alt_fin_finite_char mk_alt_fin_in by blast
    moreover have satE (Cond P H) (mk_alt_fin C)
      using propA Ks (mk_alt_fin C) Cond K unfolding propA_def by fast 
    ultimately show ?thesis
      using K all_kinds Consistency_Kind.hintikka by meson
  next
    case (Wits W)
    have witnessed (mk_mcs C S)
      using mk_mcs_witnessed[OF assms(1-3)] .
    then have p  mk_mcs C S. x. is_param x  set (W p x)  mk_mcs C S
      unfolding witnessed_def witness_def using inf_univ Wits witness_kinds K by fast
    then show ?thesis
      using Wits by fast
  qed
qed

end

locale Hintikka = Maximal_Consistency map_fm params_fm is_param Ks
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    Ks :: ('x, 'fm) kind list +
  fixes H :: 'fm set
  assumes hintikka: propH Ks H
begin

lemma satH: K  set Ks  satH K H
  using hintikka unfolding propH_def by blast

end

context Maximal_Consistency
begin

theorem mk_mcs_Hintikka:
  assumes propE Ks C S  C enough_new S
  shows Hintikka map_fm params_fm is_param Ks (mk_mcs C S)
  using assms mk_mcs_hintikka by unfold_locales

end

section ‹Derivational Consistency›

locale Derivational_Kind = Consistency_Kind map_fm params_fm is_param K
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    K :: ('x, 'fm) kind +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes kind: infinite (UNIV :: 'fm set)  satE K {A. enough_new A   A}

locale Derivational_Consistency = Maximal_Consistency map_fm params_fm is_param Ks
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    Ks :: ('x, 'fm) kind list +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes all_consistent: infinite (UNIV :: 'fm set)  propE Ks {A. enough_new A   A}
begin

theorem Consistency: propE Ks {A. enough_new A   A}
  using all_consistent inf_univ unfolding propE_def by fast

end

section ‹Weak Derivational Consistency›

locale Weak_Derivational_Kind = Consistency_Kind map_fm params_fm is_param K
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    K :: ('x, 'fm) kind +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes kind: infinite (Collect is_param)  satE K {S. A. set A = S   A}

locale Weak_Derivational_Consistency = Maximal_Consistency map_fm params_fm is_param Ks
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    Ks :: ('x, 'fm) kind list +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes Consistency: infinite (UNIV :: 'x set)  propE Ks {S. A. set A = S   A}


section ‹Conflicts›

locale Confl = Params map_fm params_fm is_param
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes classify :: 'fm list  'fm list  bool (infix  50)
  assumes confl_map: ps qs f. ps  qs  map (map_fm f) ps  map (map_fm f) qs
begin

inductive cond where
  cond [intro!]: ps  qs  cond ps (λ_ S. set qs  S = {})

inductive_cases condE[elim!]: cond ps Q

inductive hint where
  hint [intro!]: (ps qs q. ps  qs  set ps  H  q  set qs  q  H)  hint H

declare hint.simps[simp]

abbreviation kind :: ('x, 'fm) kind where
  kind  Cond cond hint

end

sublocale Confl  Consistency_Kind map_fm params_fm is_param kind
proof
  fix C
  assume conflC: satE kind C
  then show satE kind (close C)
  proof safe
    fix S ps qs q
    assume S  close C
    then obtain S' where S': S'  C and S  S'
      unfolding close_def by blast

    assume set ps  S
    then have *: set ps  S'
      using S  S' by blast

    assume **: ps  qs
    then have q  set qs. q  S'
      using conflC S' * by blast
    then have q  set qs. q  S
      using S  S' by blast
    moreover assume q  set qs q  S
    ultimately show q  {}
      using ** by auto
  qed
next
  fix C
  assume conflC: satE kind C
  then show satA kind (mk_alt_consistency C)
  proof safe
    fix S ps qs q

    assume S  mk_alt_consistency C
    then obtain f where f: map_fm f ` S  C
      unfolding mk_alt_consistency_def by blast

    let ?C = mk_alt_consistency C
    let ?S = map_fm f ` S

    assume set ps  S
    then have *: set (map (map_fm f) ps)  ?S
      by auto

    assume ps  qs
    then have map (map_fm f) ps  (map (map_fm f) qs)
      using confl_map by blast
    then have q  set  (map (map_fm f) qs). q  ?S
      using conflC f * by blast
    then have q  set qs. map_fm f q  ?S
      by simp
    then have q  set qs. q  S
      by blast
    moreover assume q  set qs q  S
    ultimately show q  {}
      by auto
  qed
next
  fix C
  assume conflAC: satA kind C and closedC: subset_closed C
  then show satA kind (mk_finite_char C)
  proof safe
    fix S ps qs q
    assume S  mk_finite_char C
    then have finc: S'  S. finite S'  S'  C
      unfolding mk_finite_char_def by blast

    have sc: S'  C. S  S'. S  C
      using closedC unfolding subset_closed_def by blast
    then have sc': S' x. x  S'  C  S  x  S'. S  C
      by blast

    assume *: set ps  S ps  qs q  set qs q  S
    then have {q}  set ps  C
      using set ps  S finc by simp
    then have q  {}
      using * conflAC by blast
    then show q  {}
      by auto
  qed
next
  fix C S
  assume *: satE kind C S  C maximal C S 
  show satH kind S
  proof safe
    fix ps qs q
    assume **: set ps  S ps  qs q  set qs q  S
    then show False
      using * by blast
  qed
qed

locale Derivational_Confl = Confl map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  'fm list  bool (infix  50) +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes consistent: S ps qs x. set ps  S  ps  qs  x  set qs  x  S  ¬  S

sublocale Derivational_Confl  Derivational_Kind map_fm params_fm is_param kind consistent
  using infinite_params_left consistent by unfold_locales blast+


locale Weak_Derivational_Confl = Confl map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  'fm list  bool (infix  50) +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes consistent: A ps qs x. set ps  set A  ps  qs  x  set qs  x  set A  ¬  A

sublocale Weak_Derivational_Confl  Weak_Derivational_Kind map_fm params_fm is_param kind consistent
  using infinite_params_left consistent by unfold_locales blast+

section ‹Alpha›

locale Alpha = Params map_fm params_fm is_param
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes classify :: 'fm list  'fm list  bool (infix α 50)
  assumes alpha_map: ps qs f. ps α qs  map (map_fm f) ps α map (map_fm f) qs
begin

inductive cond where
  cond [intro!]: ps α qs  cond ps (λC S. set qs  S  C)

inductive_cases condE[elim!]: cond ps Q

inductive hint where
  hint [intro!]: (ps qs q. ps α qs  set ps  H  q  set qs  q  H)  hint H

declare hint.simps[simp]

abbreviation kind :: ('x, 'fm) kind where
  kind  Cond cond hint

end

sublocale Alpha  Consistency_Kind map_fm params_fm is_param kind
proof
  fix C
  assume alphaC: satE kind C
  then show satE kind (close C)
  proof safe
    fix S ps qs q
    assume S  close C
    then obtain S' where S': S'  C and S  S'
      unfolding close_def by blast

    assume set ps  S ps α qs
    then have *: set ps  S'
      using S  S' by blast

    assume **: ps α qs
    then have set qs  S'  C
      using alphaC S' * by blast
    then show  set qs  S  close C
      using S  S' subset_in_close by blast
  qed
next
  fix C
  assume alphaC: satE kind C
  then show satA kind (mk_alt_consistency C)
  proof safe
    fix S ps qs

    assume S  mk_alt_consistency C
    then obtain f where f: is_subst f map_fm f ` S  C
      unfolding mk_alt_consistency_def by blast

    let ?C = mk_alt_consistency C
    let ?S = map_fm f ` S

    assume set ps  S
    then have *: set (map (map_fm f) ps)  ?S
      by auto

    assume ps α qs
    then have map (map_fm f) ps α (map (map_fm f) qs)
      using alpha_map by blast
    then have set (map (map_fm f) qs)  ?S  C
      using alphaC * f by blast
    then show set qs  S  ?C
      unfolding mk_alt_consistency_def using f by (auto simp: image_Un)
  qed
next
  fix C
  assume alphaAC: satA kind C and closedC: subset_closed C
  then show satA kind (mk_finite_char C)
  proof safe
    fix S ps qs q
    assume S  mk_finite_char C
    then have finc: S'  S. finite S'  S'  C
      unfolding mk_finite_char_def by blast

    have sc: S'  C. S  S'. S  C
      using closedC unfolding subset_closed_def by blast
    then have sc': S' x. x  S'  C  S  x  S'. S  C
      by blast

    assume *: set ps  S and **: ps α qs

    show set qs  S  mk_finite_char C
      unfolding mk_finite_char_def
    proof safe
      fix S'
      let ?S' = set ps  (S' - set qs)

      assume S'  set qs  S and finite S'
      then have ?S'  S
        using * by blast
      moreover have finite ?S'
        using finite S' by blast
      ultimately have ?S'  C
        using finc by blast
      then have set qs  ?S'  C
        using ** alphaAC by fast
      then show S'  C
        using sc by fast
    qed
  qed
next
  fix C S
  assume *: satE kind C S  C maximal C S 
  show satH kind S
  proof safe
    fix ps qs q
    assume **: set ps  S ps α qs
    then have set qs  S  C
      using * by blast
    moreover assume q  set qs
    ultimately show q  S
      using maximal C S unfolding maximal_def by fast
  qed
qed

locale Derivational_Alpha = Alpha map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  'fm list  bool (infix α 50) +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes consistent: S ps qs. set ps  S  ps α qs   S   set qs  S

sublocale Derivational_Alpha  Derivational_Kind map_fm params_fm is_param kind consistent
  using infinite_params_left consistent enough_new_def by unfold_locales blast+


locale Weak_Derivational_Alpha = Alpha map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  'fm list  bool (infix α 50) +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes consistent: A ps qs. set ps  set A  ps α qs   A   qs @ A

sublocale Weak_Derivational_Alpha  Weak_Derivational_Kind map_fm params_fm is_param kind consistent
proof
  show satE kind {S. A. set A = S   A}
  proof safe
    fix ps qs A
    assume set ps  set A ps α qs  A
    then show B. set B = set qs  set A   B
      using consistent[of ps A qs] by (meson set_append)
  qed
qed

section ‹Beta›

locale Beta = Params map_fm params_fm is_param
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes classify :: 'fm list  'fm list  bool (infix β 50)
  assumes beta_map: ps qs f. ps β qs  map (map_fm f) ps β map (map_fm f) qs
begin

inductive cond where
  cond [intro!]: ps β qs  cond ps (λC S. q  set qs. {q}  S  C)

inductive_cases condE[elim!]: cond ps Q

inductive hint where
  hint [intro!]: (ps qs. ps β qs  set ps  H  q  set qs. q  H)  hint H

declare hint.simps[simp]

abbreviation kind :: ('x, 'fm) kind where
  kind  Cond cond hint

end

sublocale Beta  Consistency_Kind map_fm params_fm is_param kind
proof
  fix C
  assume betaC: satE kind C
  then show satE kind (close C)
  proof safe
    fix S ps qs q
    assume S  close C
    then obtain S' where S': S'  C and S  S'
      unfolding close_def by blast

    assume set ps  S ps β qs
    then have *: set ps  S'
      using S  S' by blast

    assume **: ps β qs
    then have q  set qs. {q}  S'  C
      using betaC S' * by blast
    then show q  set qs. insert q S  close C
      using S  S' subset_in_close by (metis insert_is_Un)
  qed
next
  fix C
  assume betaC: satE kind C
  then show satA kind (mk_alt_consistency C)
  proof safe
    fix S ps qs

    assume S  mk_alt_consistency C
    then obtain f where f: is_subst f map_fm f ` S  C
      unfolding mk_alt_consistency_def by blast

    let ?C = mk_alt_consistency C
    let ?S = map_fm f ` S

    assume set ps  S
    then have *: set (map (map_fm f) ps)  ?S
      by auto

    assume ps β qs
    then have map (map_fm f) ps β (map (map_fm f) qs)
      using beta_map by blast
    then have q  set (map (map_fm f) qs). {q}  ?S  C
      using betaC * f by blast
    then show q  set qs. insert q S  ?C
      unfolding mk_alt_consistency_def using f by (auto simp: image_Un)
  qed
next
  fix C
  assume betaAC: satA kind C and closedC: subset_closed C
  then show satA kind (mk_finite_char C)
  proof safe
    fix S ps qs q
    assume S  mk_finite_char C
    then have finc: S'  S. finite S'  S'  C
      unfolding mk_finite_char_def by blast

    have sc: S'  C. S  S'. S  C
      using closedC unfolding subset_closed_def by blast
    then have sc': S' x. x  S'  C  S  x  S'. S  C
      by blast

    assume *: set ps  S and **: ps β qs

    show q  set qs. insert q S  mk_finite_char C
    proof (rule ccontr)
      assume ¬ ?thesis
      then have q  set qs. Sq. Sq  insert q S  finite Sq  Sq  C
        unfolding mk_finite_char_def by blast
      then obtain f where f: q  set qs. f q  insert q S  finite (f q)  f q  C
        by metis

      let ?S' = set ps  {f q - {q} |q. q  set qs}

      have ?S'  S
        using * f by fast
      moreover have finite ?S'
        using f by auto
      ultimately have ?S'  C
        using finc by blast
      then have q  set qs. {q}  ?S'  C
        using ** betaAC by fast
      then have q  set qs. f q  C
        using sc' by blast
      then show False
        using f by blast
    qed
  qed
next
  fix C S
  assume *: satE kind C S  C maximal C S 
  show satH kind S
  proof safe
    fix ps qs
    assume **: set ps  S ps β qs
    then have q  set qs. {q}  S  C
      using * by blast
    then show q  set qs. q  S
      using maximal C S unfolding maximal_def by fast
  qed
qed

locale Derivational_Beta = Beta map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  'fm list  bool (infix β 50) +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes consistent: S ps qs. set ps  S  ps β qs   S  q  set qs.  {q}  S

sublocale Derivational_Beta  Derivational_Kind map_fm params_fm is_param kind consistent
proof
  assume inf: infinite (UNIV :: 'fm set)
  then show satE kind {A. enough_new A   A}
  proof safe
    fix S ps qs
    assume *: set ps  S ps β qs  S
    then have q  set qs.  {q}  S
      using consistent by blast
    moreover assume enough_new S 
    ultimately show qset qs. insert q S  {A. enough_new A   A}
      using infinite_params_left[OF inf] unfolding enough_new_def
      by (metis (no_types, lifting) empty_set insert_code(1) insert_is_Un mem_Collect_eq)
  qed
qed

locale Weak_Derivational_Beta = Beta map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  'fm list  bool (infix β 50) +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes consistent: A ps qs. set ps  set A  ps β qs   A  q  set qs.  q # A

sublocale Weak_Derivational_Beta  Weak_Derivational_Kind map_fm params_fm is_param kind consistent
proof
  show satE kind {S. A. set A = S   A}
  proof safe
    fix ps qs A
    assume *: set ps  set A ps β qs  A
    then have q  set qs.  q # A
      using consistent by blast
    then show qset qs. insert q (set A)  {S. A. set A = S   A}
      by (metis (mono_tags, lifting) CollectI list.simps(15))
  qed
qed

section ‹Gamma›

locale Gamma = Params map_fm params_fm is_param
  for
    map_tm :: ('x  'x)  'tm  'tm and
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes classify :: 'fm list  ('fm set  'tm set) × ('tm  'fm list)  bool (infix γ 50)
  assumes gamma_map: ps F qs f. ps γ (F, qs)  (G rs. map (map_fm f) ps γ (G, rs) 
      (S. map_tm f ` F S  G (map_fm f ` S)) 
      (t. map (map_fm f) (qs t) = rs (map_tm f t)))
    and gamma_mono: ps F qs S S'. ps γ (F, qs)  S  S'  F S  F S'
    and gamma_fin: ps F qs t A. ps γ (F, qs)  t  F A  B  A. finite B  t  F B
begin

inductive cond where
  cond [intro!]: ps γ (F, qs)  cond ps (λC S. t  F S. set (qs t)  S  C)

inductive_cases condE[elim!]: cond ps Q

inductive hint where
  hint [intro!]: (ps F qs. ps γ (F, qs)  set ps  H  (t  F H. set (qs t)  H))  hint H

declare hint.simps[simp]

abbreviation kind :: ('x, 'fm) kind where
  kind  Cond cond hint

end

sublocale Gamma  Consistency_Kind map_fm params_fm is_param kind
proof
  fix C
  assume gammaC: satE kind C
  then show satE kind (close C)
  proof safe
    fix S ps qs F t
    assume S  close C
    then obtain S' where S': S'  C and S  S'
      unfolding close_def by blast

    assume set ps  S
    then have *: set ps  S'
      using S  S' by blast

    assume **: ps γ (F, qs) t  F S
    then have t  F S'
      using ** gamma_mono S  S' by blast
    then have set (qs t)  S'  C
      using gammaC S' * ** by blast
    then have set (qs t)  S  close C
      using S  S' subset_in_close by blast
    then show set (qs t)  S  close C
      by (meson close_closed equalityE subset_closed_def sup.mono)
  qed
next
  fix C
  assume gammaC: satE kind C
  then show satA kind (mk_alt_consistency C)
  proof safe
    fix S ps F qs t

    assume S  mk_alt_consistency C
    then obtain f where f: is_subst f map_fm f ` S  C
      unfolding mk_alt_consistency_def by blast

    let ?C = mk_alt_consistency C
    let ?S = map_fm f ` S

    assume set ps  S
    then have *: set (map (map_fm f) ps)  ?S
      by auto

    assume **: ps γ (F, qs) and t: t  F S
    obtain rs G where rs:
      map (map_fm f) ps γ (G, rs)
      S. map_tm f ` F S  G (map_fm f ` S)
      t. map (map_fm f) (qs t) = rs (map_tm f t)
      using gamma_map ** by meson
    then have set (rs (map_tm f t))  ?S  C
      using gammaC f * t by blast
    then have set (map (map_fm f) (qs t))  ?S  C
      using rs by simp
    then show set (qs t)  S  ?C
      unfolding mk_alt_consistency_def using f by (auto simp: image_Un)
  qed
next
  fix C
  assume gammaAC: satA kind C and closedC: subset_closed C
  then show satA kind (mk_finite_char C)
  proof safe
    fix S ps F qs t
    assume S  mk_finite_char C
    then have finc: S'  S. finite S'  S'  C
      unfolding mk_finite_char_def by blast

    have sc: S'  C. S  S'. S  C
      using closedC unfolding subset_closed_def by blast
    then have sc': S' x. x  S'  C  S  x  S'. S  C
      by blast

    assume *: set ps  S and **: ps γ (F, qs) and t: t  F S

    show set (qs t)  S  mk_finite_char C
      unfolding mk_finite_char_def 
    proof safe
      fix S'
      assume 1: S'  set (qs t)  S and 2: finite S'

      obtain A where A: A  S finite A S'  set (qs t)  A 
        using 1 2 by (meson Diff_subset_conv equalityD2 finite_Diff)

      obtain B where B: B  S finite B t  F B
        using ** t gamma_fin by meson

      let ?S = set ps  A  B

      have finite ?S
        using A(2) B(2) by blast
      moreover have ?S  S
        using * A(1) B(1) by simp
      ultimately have ?S  C
        using finc by simp

      moreover have set ps  ?S
        by blast
      moreover have t  F ?S
        using ** B(3) gamma_mono by blast
      ultimately have set (qs t)  ?S  C
        using ** gammaAC by blast

      moreover have S'  set (qs t)  ?S
        using A(3) by blast
      ultimately show S'  C
        using sc by blast
    qed
  qed
next
  fix C S
  assume *: satE kind C S  C maximal C S 
  show satH kind S
  proof safe
    fix ps F qs t
    assume **: set ps  S ps γ (F, qs)
    then have t  F S. set (qs t)  S  C
      using * by blast
    then have t  F S. set (qs t)  S
      using maximal C S unfolding maximal_def by fast
    then show t  F S  x  set (qs t)  x  S for x
      by blast
  qed
qed

locale Derivational_Gamma = Gamma map_tm map_fm params_fm is_param classify
  for
    map_tm :: ('x  'x)  'tm  'tm and
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  ('fm set  'tm set) × ('tm  'fm list)  bool (infix γ 50) +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes consistent: S ps F qs t. set ps  S  ps γ (F, qs)  t  F S   S   set (qs t)  S

sublocale Derivational_Gamma  Derivational_Kind map_fm params_fm is_param kind consistent
  using infinite_params_left consistent enough_new_def by unfold_locales blast+

locale Weak_Derivational_Gamma = Gamma map_tm map_fm params_fm is_param classify
  for
    map_tm :: ('x  'x)  'tm  'tm and
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  ('fm set  'tm set) × ('tm  'fm list)  bool (infix γ 50) +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes consistent: A ps F qs t. set ps  set A  ps γ (F, qs)  t  F (set A)   A   qs t @ A

sublocale Weak_Derivational_Gamma  Weak_Derivational_Kind map_fm params_fm is_param kind consistent
proof
  show satE kind {S. A. set A = S   A}
  proof safe
    fix ps qs A F t
    assume *: set ps  set A ps γ (F, qs)  A t  F (set A)
    then show B. set B = set (qs t)  set A   B
      using consistent[of ps A F qs t] by (meson set_append)
  qed
qed

locale Gamma_UNIV = Params map_fm params_fm is_param
  for
    map_tm :: ('x  'x)  'tm  'tm and
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes classify :: 'fm list  ('tm  'fm list)  bool (infix γ'' 50)
  assumes gamma_map_UNIV: ps qs f. ps γ' qs  rs. map (map_fm f) ps γ' rs 
      (t. map (map_fm f) (qs t) = rs (map_tm f t))
begin

abbreviation (input) classify_UNIV where
  classify_UNIV  λps (F, qs). (F = (λ_. UNIV))  ps γ' qs

end

sublocale Gamma_UNIV  Gamma map_tm map_fm params_fm is_param classify_UNIV
proof
  show ps F qs f.
       (case (F, qs) of (F, qs)  F = (λ_. UNIV)  ps γ' qs) 
       G rs.
          (case (G, rs) of (F, qs)  F = (λ_. UNIV)  map (map_fm f) ps γ' qs) 
          (S. map_tm f ` F S  G (map_fm f ` S))  (t. map (map_fm f) (qs t) = rs (map_tm f t))
    using gamma_map_UNIV image_subset_iff by fastforce
  show ps F qs S S'. (case (F, qs) of (F, qs)  F = (λ_. UNIV)  ps γ' qs)  S  S'  F S  F S'
    by simp
  show ps F qs t A. (case (F, qs) of (F, qs)  F = (λ_. UNIV)  ps γ' qs)  t  F A  BA. finite B  t  F B
    by blast
qed

section ‹Delta›

locale Delta = Params map_fm params_fm is_param
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes δ :: 'fm  'x  'fm list
  assumes delta_map: p f x. is_param x  is_subst f  δ (map_fm f p) (f x) = map (map_fm f) (δ p x)
begin

abbreviation kind  Wits δ
end

sublocale Delta  Consistency_Kind map_fm params_fm is_param kind
proof
  fix C
  assume deltaC: satE kind C
  then show satE kind (close C)
  proof safe
    fix S p qs q
    assume S  close C
    then obtain S' where S': S'  C and S  S'
      unfolding close_def by blast

    assume p  S
    then have *: p  S'
      using S  S' by blast

    have x. is_param x  set (δ p x)  S'  C
      using deltaC S' * by blast
    then show x. is_param x  set (δ p x)  S  close C
      using S  S' by (metis subset_in_close)

  qed
next
  fix C
  assume deltaC: satE kind C
  then show satA kind (mk_alt_consistency C)
  proof safe
    fix S p qs x

    assume S  mk_alt_consistency C
    then obtain f where f: is_subst f map_fm f ` S  C
      unfolding mk_alt_consistency_def by blast

    let ?C = mk_alt_consistency C
    let ?S = map_fm f ` S

    assume p  S
    then have *: map_fm f p  ?S
      by auto

    assume x: x  params S is_param x
    obtain y where y: is_param y set (δ (map_fm f p) y)  ?S  C
      using deltaC f * by blast

    let ?g = f(x := y)

    have g: is_subst ?g
      using f x y unfolding is_subst_def by simp

    have x  params S. f x = ?g x
      using x by simp
    then have S: q  S. map_fm ?g q = map_fm f q
      using map_params_fm by simp
    then have map_fm ?g p = map_fm f p
      using p  S by auto

    moreover have set (δ (map_fm f p) (?g x))  ?S  C
      using y by simp
    ultimately have set (map (map_fm ?g) (δ p x))  ?S  C
      using delta_map x g by metis
    then have f. is_subst f  set (map (map_fm f) (δ p x))  map_fm f ` S  C
      using S g by (metis image_cong)
    then show set (δ p x)  S  ?C
      unfolding mk_alt_consistency_def
      by (metis (mono_tags, lifting) image_Un image_set mem_Collect_eq)
  qed
next
  fix C
  assume deltaAC: satA kind C and closedC: subset_closed C
  then show satA kind (mk_finite_char C)
  proof safe
    fix S p qs x
    assume S  mk_finite_char C
    then have finc: S'  S. finite S'  S'  C
      unfolding mk_finite_char_def by blast

    have sc: S'  C. S  S'. S  C
      using closedC unfolding subset_closed_def by blast
    then have sc': S' x. x  S'  C  S  x  S'. S  C
      by blast

    assume *: p  S and x: x  params S is_param x
    show set (δ p x)  S  mk_finite_char C
      unfolding mk_finite_char_def
    proof safe
      fix S'
      let ?S' = {p}  (S' - set (δ p x))

      assume S'  set (δ p x)  S and finite S'
      then have ?S'  S
        using * by fast
      moreover have finite ?S'
        using finite S' by blast
      ultimately have ?S'  C
        using finc by blast
      moreover have a  ?S'. x  params_fm a
        using x ?S'  S by blast
      ultimately have set (δ p x)  ?S'  C
        using x deltaAC by blast
      then show S'  C
        using sc by fast
    qed
  qed
next
  show C S. satE kind C  S  C  maximal C S  satH kind S
    using satH_Wits .
qed

locale Derivational_Delta = Delta map_fm params_fm is_param δ
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    δ :: 'fm  'x  'fm list +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes consistent: S p x. p  S  is_param x  x  params S   S   set (δ p x)  S

sublocale Derivational_Delta  Derivational_Kind map_fm params_fm is_param kind consistent
proof
  assume inf: infinite (UNIV :: 'fm set)
  show satE kind {A. enough_new A   A}
  proof safe
    fix S p
    assume *: p  S enough_new S  S
    then have infinite (Collect is_param - (params ({p}  S)))
      unfolding enough_new_def using card_of_ordLeq_finite inf by auto
    then obtain x where is_param x x  params ({p}  S)
      using infinite_imp_nonempty by blast
    then have x. is_param x   set (δ p x)  S
      using *(1,3) consistent  S by fast
    then show x. is_param x  set (δ p x)  S  {A. enough_new A   A}
      using * inf infinite_params_left unfolding enough_new_def by blast
  qed
qed

locale Weak_Derivational_Delta = Delta map_fm params_fm is_param δ
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    δ :: 'fm  'x  'fm list +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes consistent: A p x. p  set A  is_param x  x  params (set A)   A   δ p x @ A

sublocale Weak_Derivational_Delta  Weak_Derivational_Kind map_fm params_fm is_param kind consistent
proof
  assume inf: infinite (Collect is_param :: 'x set)
  show satE kind {S. A. set A = S   A}
  proof safe
    fix p A
    assume *: p  set A  A
    then have infinite (Collect is_param - (params (set (p # A))))
      using inf finite_compl by fastforce
    then obtain x where is_param x x  params (set (p # A))
      using infinite_imp_nonempty by blast
    then have x. is_param x   δ p x @ A
      using * consistent[of p A x] by auto
    then show x. is_param x  set (δ p x)  set A  {S. A. set A = S   A}
      by (metis (mono_tags, lifting) CollectI set_append)
  qed
qed

section ‹Modal›

text ‹
  The Hintikka property you want depends on the concrete logic.
  See Term-Modal Logics by Fitting, Thalmann and Voronkov, p. 156 bottom.
›

locale Modal = Params map_fm params_fm is_param
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool +
  fixes classify :: 'fm list  ('fm set  'fm set) × 'fm list  bool (infix  50)
    and hint :: 'fm set  bool
  assumes modal_map: ps F qs f. ps  (F, qs)  G. map (map_fm f) ps  (G, map (map_fm f) qs) 
      (S. map_fm f ` F S  G (map_fm f ` S))
    and modal_mono: ps F qs S S'. ps  (F, qs)  S  S'  F S  F S'
    and modal_fin: ps F qs S A. ps  (F, qs)  finite A  A  F S  S'  S. finite S'  A  F S'
begin

inductive cond where
  cond [intro!]: ps  (F, qs)  cond ps (λC S. set qs  F S  C)

inductive_cases condE[elim!]: cond ps Q

abbreviation kind :: ('x, 'fm) kind where
  kind  Cond cond hint

end

locale ModalH = Modal map_fm params_fm is_param classify hint
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  ('fm set  'fm set) × 'fm list  bool (infix  50) and
    hint :: 'fm set  bool +
  assumes modal_hintikka: C S. satE kind C  S  C  maximal C S  satH kind S

sublocale ModalH  Consistency_Kind map_fm params_fm is_param kind
proof
  fix C
  assume modalC: satE kind C
  then show satE kind (close C)
  proof safe
    fix S ps F qs
    assume S  close C
    then obtain S' where S': S'  C and S  S'
      unfolding close_def by blast

    assume set ps  S
    then have *: set ps  S'
      using S  S' by blast

    assume **: ps  (F, qs)
    then have set qs  F S'  C
      using modalC S' * ** by blast
    then show set qs  F S  close C
      using S  S' subset_in_close ** modal_mono by metis
  qed
next
  fix C
  assume modalC: satE kind C and closedC: subset_closed C
  then show satA kind (mk_alt_consistency C)
  proof safe
    fix S ps F qs

    assume S  mk_alt_consistency C
    then obtain f where f: is_subst f map_fm f ` S  C
      unfolding mk_alt_consistency_def by blast

    let ?C = mk_alt_consistency C
    let ?S = map_fm f ` S

    assume set ps  S
    then have *: set (map (map_fm f) ps)  ?S
      by auto

    assume **: ps  (F, qs)
    obtain G where G:
      map (map_fm f) ps  (G, map (map_fm f) qs)
      S. map_fm f ` F S  G (map_fm f ` S)
      using modal_map ** by meson
    then have set (map (map_fm f) qs)  G ?S  C
      using modalC f * by blast
    then have set (map (map_fm f) qs)  map_fm f ` F S  C
      using G closedC unfolding subset_closed_def by (meson Un_mono order_refl)
    then show set qs  F S  ?C
      unfolding mk_alt_consistency_def using f
      by (auto split: option.splits simp: image_Un)
  qed
next
  fix C
  assume modalAC: satA kind C and closedC: subset_closed C
  then show satA kind (mk_finite_char C)
  proof safe
    fix S ps F qs t
    assume S: S  mk_finite_char C
    then have finc: S'  S. finite S'  S'  C
      unfolding mk_finite_char_def by blast

    have sc: S'  C. S  S'. S  C
      using closedC unfolding subset_closed_def by blast
    then have sc': S' x. x  S'  C  S  x  S'. S  C
      by blast

    assume *: set ps  S and **: ps  (F, qs)

    show set qs  F S  mk_finite_char C
      unfolding mk_finite_char_def 
    proof safe
      fix S'
      assume 1: S'  set qs  F S and 2: finite S'

      obtain A where A: A  S finite A S'  set qs  F A 
        using 1 2 ** modal_fin by (meson Diff_subset_conv finite_Diff)

      let ?S = set ps  A

      have finite ?S
        using A(2) by blast
      moreover have ?S  S
        using * A(1) by simp
      ultimately have ?S  C
        using finc by simp

      moreover have set ps  ?S
        by blast
      ultimately have set qs  F ?S  C
        using ** modalAC by blast

      moreover have S'  set qs  F ?S
        using A(3) ** modal_mono by (meson Diff_subset_conv inf_sup_ord(4) subset_trans)
      ultimately show S'  C
        using sc by blast
    qed
  qed
next
  fix C S
  assume *: satE kind C S  C maximal C S 
  then show satH kind S
    using modal_hintikka by simp
qed

locale Derivational_Modal = ModalH map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  ('fm set  'fm set) × 'fm list  bool (infix  50) +
  fixes consistent :: 'fm set  bool ( _› [51] 50)
  assumes consistent: S ps F qs. set ps  S  ps  (F, qs)   S   set qs  F S
    and params_subset: ps F qs S. ps  (F, qs)  params (F S)  params S

sublocale Derivational_Modal  Derivational_Kind map_fm params_fm is_param kind consistent
proof
  assume inf: infinite (UNIV :: 'fm set)
  then show satE kind {A. enough_new A   A}
  proof safe
    fix S ps F qs
    assume ps  (F, qs) enough_new S
    then have enough_new (F S)
      unfolding enough_new_def using params_subset[of ps F qs S] ordLeq_transitive
        card_of_mono1[of "Collect is_param - params S" "Collect is_param - params (F S)"]
      by blast
    then show enough_new (set qs  F S)
      using infinite_params_left[OF inf] unfolding enough_new_def by blast
  qed (use consistent in blast)
qed

locale Weak_Derivational_Modal = ModalH map_fm params_fm is_param classify
  for
    map_fm :: ('x  'x)  'fm  'fm and
    params_fm :: 'fm  'x set and
    is_param :: 'x  bool and
    classify :: 'fm list  ('fm set  'fm set) × 'fm list  bool (infix  50) +
  fixes consistent :: 'fm list  bool ( _› [51] 50)
  assumes consistent: S ps F qs S'. set ps  set S  ps  (F, qs)   S  set S' = F (set S)   qs @ S'
    and params_subset: ps F qs S. ps  (F, qs)  params (F S)  params S
    and F_size: ps F qs S. ps  (F, qs)  |F S| ≤o |S|

sublocale Weak_Derivational_Modal  Weak_Derivational_Kind map_fm params_fm is_param kind consistent
proof
  assume inf: infinite (Collect is_param :: 'x set)
  show satE kind {S. A. set A = S   A}
  proof safe
    fix ps qs A F
    assume set ps  set A ps  (F, qs)  A
    then show B. set B = set qs  F (set A)   B
      using consistent[of ps A F qs] F_size
      by (metis card_of_ordLeq_infinite finite_list list.set_finite set_append)
  qed
qed

end