Session Forcing

Theory Utils

theory Utils
  imports "ZF-Constructible.Formula"
begin

ML_file ‹utils.ML›

end

File ‹utils.ML›

signature UTILS =
 sig
    val binop : term -> term -> term -> term
    val add_: term -> term -> term
    val app_: term -> term -> term
    val concat_: term -> term -> term
    val dest_apply: term -> term * term
    val dest_iff_lhs: term -> term
    val dest_iff_rhs: term -> term
    val dest_iff_tms: term -> term * term
    val dest_lhs_def: term -> term
    val dest_rhs_def: term -> term
    val dest_satisfies_tms: term -> term * term
    val dest_satisfies_frm: term -> term
    val dest_eq_tms: term -> term * term
    val dest_sats_frm: term -> (term * term) * term
    val dest_trueprop: term -> term
    val eq_: term -> term -> term
    val fix_vars: thm -> string list -> Proof.context -> thm
    val formula_: term
    val freeName: term -> string
    val inList: ''a -> ''a list -> bool
    val isFree: term -> bool
    val length_: term -> term
    val list_: term -> term
    val lt_: term -> term -> term
    val mem_: term -> term -> term
    val mk_FinSet: term list -> term
    val mk_Pair: term -> term -> term
    val mk_ZFlist: ('a -> term) -> 'a list -> term
    val mk_ZFnat: int -> term
    val nat_: term
    val nth_: term -> term -> term
    val subset_: term -> term -> term
    val thm_concl_tm :  Proof.context -> xstring -> 
        ((indexname * typ) * cterm) list * term * Proof.context
    val to_ML_list: term -> term list
    val tp: term -> term
  end

structure Utils : UTILS =
struct 
(* Smart constructors for ZF-terms *)

fun inList a = exists (fn b => a = b)

fun binop h t u = h $ t $ u
val mk_Pair  = binop @{const Pair}

fun mk_FinSet nil = @{const zero}
  | mk_FinSet (e :: es) = @{const cons} $ e $ mk_FinSet es

fun mk_ZFnat 0 = @{const zero}
  | mk_ZFnat n = @{const succ} $ mk_ZFnat (n-1)

fun mk_ZFlist _ nil = @{const "Nil"}
  | mk_ZFlist f (t :: ts) = @{const "Cons"} $ f t $ mk_ZFlist f ts

fun to_ML_list (@{const Nil}) = nil
  | to_ML_list (@{const Cons} $ t $ ts) = t :: to_ML_list ts
|   to_ML_list _ = nil

fun isFree (Free (_,_)) = true
  | isFree _ = false

fun freeName (Free (n,_)) = n
  | freeName _ = error "Not a free variable"

val app_ = binop @{const apply}

fun tp x = @{const Trueprop} $ x
fun length_ env = @{const length} $ env
val nth_ = binop @{const nth}
val add_ = binop @{const add}
val mem_ = binop @{const mem}
val subset_ = binop @{const Subset}
val lt_ = binop @{const lt}
val concat_ = binop @{const app}
val eq_ = binop @{const IFOL.eq(i)}

(* Abbreviation for sets *)
fun list_ set = @{const list} $ set
val nat_ = @{const nat}
val formula_ = @{const formula}

(** Destructors of terms **)
fun dest_eq_tms (Const (@{const_name IFOL.eq},_) $ t $ u) = (t, u)
  | dest_eq_tms t = raise TERM ("dest_eq_tms", [t])

fun dest_lhs_def (Const (@{const_name Pure.eq},_) $ x $ _) = x
  | dest_lhs_def t = raise TERM ("dest_lhs_def", [t])

fun dest_rhs_def (Const (@{const_name Pure.eq},_) $ _ $ y) = y
  | dest_rhs_def t = raise TERM ("dest_rhs_def", [t])


fun dest_apply (@{const apply} $ t $ u) = (t,u)
  | dest_apply t = raise TERM ("dest_applies_op", [t])

fun dest_satisfies_tms (@{const Formula.satisfies} $ A $ f) = (A,f)
  | dest_satisfies_tms t = raise TERM ("dest_satisfies_tms", [t]);

val dest_satisfies_frm = #2 o dest_satisfies_tms

fun dest_sats_frm t = t |> dest_eq_tms |> #1 |> dest_apply |>> dest_satisfies_tms ;

fun dest_trueprop (@{const IFOL.Trueprop} $ t) = t
  | dest_trueprop t = t

fun dest_iff_tms (@{const IFOL.iff} $ t $ u) = (t, u)
  | dest_iff_tms t = raise TERM ("dest_iff_tms", [t])

val dest_iff_lhs = #1 o dest_iff_tms
val dest_iff_rhs = #2 o dest_iff_tms

fun thm_concl_tm ctxt thm_ref =
  let val (((_,vars),thm_tms),ctxt1) = Variable.import true [Proof_Context.get_thm ctxt thm_ref] ctxt
  in (vars, thm_tms |> hd |> Thm.concl_of, ctxt1)
end

fun fix_vars thm vars ctxt = let
  val (_, ctxt1) = Variable.add_fixes vars ctxt
  in singleton (Proof_Context.export ctxt1 ctxt) thm
end

end ;

Theory Forcing_Notions

section‹Forcing notions›
text‹This theory defines a locale for forcing notions, that is,
 preorders with a distinguished maximum element.›

theory Forcing_Notions
  imports "ZF-Constructible.Relative"
begin

subsection‹Basic concepts›
text‹We say that two elements $p,q$ are
  ‹compatible› if they have a lower bound in $P$›
definition compat_in :: "iiiio" where
  "compat_in(A,r,p,q)  dA . d,pr  d,qr"

definition
  is_compat_in :: "[io,i,i,i,i]  o" where
  "is_compat_in(M,A,r,p,q)  d[M]. dA  (dp[M]. pair(M,d,p,dp)  dpr  
                                   (dq[M]. pair(M,d,q,dq)  dqr))"

lemma compat_inI : 
  " dA ; d,pr ; d,gr   compat_in(A,r,p,g)"
  by (auto simp add: compat_in_def)

lemma refl_compat:
  " refl(A,r) ; p,q  r | p=q | q,p  r ; pA ; qA  compat_in(A,r,p,q)"
  by (auto simp add: refl_def compat_inI)

lemma  chain_compat:
  "refl(A,r)  linear(A,r)   (pA.qA. compat_in(A,r,p,q))"
  by (simp add: refl_compat linear_def)

lemma subset_fun_image: "f:NP  f``NP"
  by (auto simp add: image_fun apply_funtype)

lemma refl_monot_domain: "refl(B,r)  AB  refl(A,r)"  
  unfolding refl_def by blast

definition
  antichain :: "iiio" where
  "antichain(P,leq,A)  AP  (pA.qA.(¬ compat_in(P,leq,p,q)))"

definition 
  ccc :: "i  i  o" where
  "ccc(P,leq)  A. antichain(P,leq,A)  |A|  nat"

locale forcing_notion =
  fixes P leq one
  assumes one_in_P:         "one  P"
    and leq_preord:       "preorder_on(P,leq)"
    and one_max:          "pP. p,oneleq"
begin

abbreviation Leq :: "[i, i]  o"  (infixl "" 50)
  where "x  y  x,yleq"

lemma refl_leq:
  "rP  rr"
  using leq_preord unfolding preorder_on_def refl_def by simp

text‹A set $D$ is ‹dense› if every element $p\in P$ has a lower 
bound in $D$.›
definition 
  dense :: "io" where
  "dense(D)  pP. dD . dp"

text‹There is also a weaker definition which asks for 
a lower bound in $D$ only for the elements below some fixed 
element $q$.›
definition 
  dense_below :: "iio" where
  "dense_below(D,q)  pP. pq  (dD. dP  dp)"

lemma P_dense: "dense(P)"
  by (insert leq_preord, auto simp add: preorder_on_def refl_def dense_def)

definition 
  increasing :: "io" where
  "increasing(F)  xF.  p  P . xp  pF"

definition 
  compat :: "iio" where
  "compat(p,q)  compat_in(P,leq,p,q)"

lemma leq_transD:  "ab  bc  a  P b  P c  P ac"
  using leq_preord trans_onD unfolding preorder_on_def by blast

lemma leq_transD':  "AP  ab  bc  a  A  b  P c  P ac"
  using leq_preord trans_onD subsetD unfolding preorder_on_def by blast


lemma leq_reflI: "pP  pp"
  using leq_preord unfolding preorder_on_def refl_def by blast

lemma compatD[dest!]: "compat(p,q)  dP. dp  dq"
  unfolding compat_def compat_in_def .

abbreviation Incompatible :: "[i, i]  o"  (infixl "" 50)
  where "p  q  ¬ compat(p,q)"

lemma compatI[intro!]: "dP  dp  dq  compat(p,q)"
  unfolding compat_def compat_in_def by blast

lemma denseD [dest]: "dense(D)  pP   dD. d p"
  unfolding dense_def by blast

lemma denseI [intro!]: " p. pP  dD. d p   dense(D)"
  unfolding dense_def by blast

lemma dense_belowD [dest]:
  assumes "dense_below(D,p)" "qP" "qp"
  shows "dD. dP  dq"
  using assms unfolding dense_below_def by simp
    (*obtains d where "d∈D" "d∈P" "d≼q"
  using assms unfolding dense_below_def by blast *)

lemma dense_belowI [intro!]: 
  assumes "q. qP  qp  dD. dP  dq" 
  shows "dense_below(D,p)"
  using assms unfolding dense_below_def by simp

lemma dense_below_cong: "pP  D = D'  dense_below(D,p)  dense_below(D',p)"
  by blast

lemma dense_below_cong': "pP  x. xP  Q(x)  Q'(x)  
           dense_below({qP. Q(q)},p)  dense_below({qP. Q'(q)},p)"
  by blast

lemma dense_below_mono: "pP  D  D'  dense_below(D,p)  dense_below(D',p)"
  by blast

lemma dense_below_under:
  assumes "dense_below(D,p)" "pP" "qP" "qp"
  shows "dense_below(D,q)"
  using assms leq_transD by blast

lemma ideal_dense_below:
  assumes "q. qP  qp  qD"
  shows "dense_below(D,p)"
  using assms leq_reflI by blast

lemma dense_below_dense_below: 
  assumes "dense_below({qP. dense_below(D,q)},p)" "pP" 
  shows "dense_below(D,p)"  
  using assms leq_transD leq_reflI  by blast
    (* Long proof *)
    (*  unfolding dense_below_def
proof (intro ballI impI)
  fix r
  assume "r∈P" ‹r≼p›
  with assms
  obtain q where "q∈P" "q≼r" "dense_below(D,q)"
    using assms by auto
  moreover from this
  obtain d where "d∈P" "d≼q" "d∈D"
    using assms leq_preord unfolding preorder_on_def refl_def by blast
  moreover
  note ‹r∈P›
  ultimately
  show "∃d∈D. d ∈ P ∧ d≼ r"
    using leq_preord trans_onD unfolding preorder_on_def by blast
qed *)

definition
  antichain :: "io" where
  "antichain(A)  AP  (pA.qA.(¬compat(p,q)))"

text‹A filter is an increasing set $G$ with all its elements 
being compatible in $G$.›
definition 
  filter :: "io" where
  "filter(G)  GP  increasing(G)  (pG. qG. compat_in(G,leq,p,q))"

lemma filterD : "filter(G)  x  G  x  P"
  by (auto simp add : subsetD filter_def)

lemma filter_leqD : "filter(G)  x  G  y  P  xy  y  G"
  by (simp add: filter_def increasing_def)

lemma filter_imp_compat: "filter(G)  pG  qG  compat(p,q)"
  unfolding filter_def compat_in_def compat_def by blast

lemma low_bound_filter: ― ‹says the compatibility is attained inside G›
  assumes "filter(G)" and "pG" and "qG"
  shows "rG. rp  rq" 
  using assms 
  unfolding compat_in_def filter_def by blast

text‹We finally introduce the upward closure of a set
and prove that the closure of $A$ is a filter if its elements are
compatible in $A$.›
definition  
  upclosure :: "ii" where
  "upclosure(A)  {pP.aA. ap}"

lemma  upclosureI [intro] : "pP  aA  ap  pupclosure(A)"
  by (simp add:upclosure_def, auto)

lemma  upclosureE [elim] :
  "pupclosure(A)  (x a. xP  aA  ax  R)  R"
  by (auto simp add:upclosure_def)

lemma  upclosureD [dest] :
  "pupclosure(A)  aA.(ap)  pP"
  by (simp add:upclosure_def)

lemma upclosure_increasing :
  assumes "AP"
  shows "increasing(upclosure(A))"
  unfolding increasing_def upclosure_def
  using leq_transD'[OF AP] by auto

lemma  upclosure_in_P: "A  P  upclosure(A)  P"
  using subsetI upclosure_def by simp

lemma  A_sub_upclosure: "A  P  Aupclosure(A)"
  using subsetI leq_preord 
  unfolding upclosure_def preorder_on_def refl_def by auto

lemma  elem_upclosure: "AP  xA   xupclosure(A)"
  by (blast dest:A_sub_upclosure)

lemma  closure_compat_filter:
  assumes "AP" "(pA.qA. compat_in(A,leq,p,q))"
  shows "filter(upclosure(A))"
  unfolding filter_def
proof(auto)
  show "increasing(upclosure(A))"
    using assms upclosure_increasing by simp
next
  let ?UA="upclosure(A)"
  show "compat_in(upclosure(A), leq, p, q)" if "p?UA" "q?UA" for p q
  proof -
    from that
    obtain a b where 1:"aA" "bA" "ap" "bq" "pP" "qP"
      using upclosureD[OF p?UA] upclosureD[OF q?UA] by auto
    with assms(2)
    obtain d where "dA" "da" "db"
      unfolding compat_in_def by auto
    with 1
    have 2:"dp" "dq" "d?UA"
      using A_sub_upclosure[THEN subsetD] AP
        leq_transD'[of A d a] leq_transD'[of A d b] by auto
    then
    show ?thesis unfolding compat_in_def by auto
  qed
qed

lemma  aux_RS1:  "f  N  P  nN  f`n  upclosure(f ``N)"
  using elem_upclosure[OF subset_fun_image] image_fun
  by (simp, blast)

lemma decr_succ_decr: 
  assumes "f  nat  P" "preorder_on(P,leq)"
    "nnat.  f ` succ(n), f ` n  leq"
    "mnat"
  shows "nnat  nm  f ` m, f ` n  leq"
  using m_
proof(induct m)
  case 0
  then show ?case using assms leq_reflI by simp
next
  case (succ x)
  then
  have 1:"f`succ(x)  f`x" "f`nP" "f`xP" "f`succ(x)P"
    using assms by simp_all
  consider (lt) "n<succ(x)" | (eq) "n=succ(x)"
    using succ le_succ_iff by auto
  then 
  show ?case 
  proof(cases)
    case lt
    with 1 show ?thesis using leI succ leq_transD by auto
  next
    case eq
    with 1 show ?thesis using leq_reflI by simp
  qed
qed

lemma decr_seq_linear: 
  assumes "refl(P,leq)" "f  nat  P"
    "nnat.  f ` succ(n), f ` n  leq"
    "trans[P](leq)"
  shows "linear(f `` nat, leq)"
proof -
  have "preorder_on(P,leq)" 
    unfolding preorder_on_def using assms by simp
  {
    fix n m
    assume "nnat" "mnat"
    then
    have "f`m  f`n  f`n  f`m"
    proof(cases "mn")
      case True
      with n_ m_
      show ?thesis 
        using decr_succ_decr[of f n m] assms leI ‹preorder_on(P,leq) by simp
    next
      case False
      with n_ m_
      show ?thesis 
        using decr_succ_decr[of f m n] assms leI not_le_iff_lt ‹preorder_on(P,leq) by simp
    qed
  }
  then
  show ?thesis
    unfolding linear_def using ball_image_simp assms by auto
qed

end (* forcing_notion *)

subsection‹Towards Rasiowa-Sikorski Lemma (RSL)›
locale countable_generic = forcing_notion +
  fixes 𝒟
  assumes countable_subs_of_P:  "𝒟  natPow(P)"
    and     seq_of_denses:        "n  nat. dense(𝒟`n)"

begin

definition
  D_generic :: "io" where
  "D_generic(G)  filter(G)  (nnat.(𝒟`n)G0)"

text‹The next lemma identifies a sufficient condition for obtaining
RSL.›
lemma RS_sequence_imp_rasiowa_sikorski:
  assumes 
    "pP" "f : natP" "f ` 0 = p"
    "n. nnat  f ` succ(n) f ` n  f ` succ(n)  𝒟 ` n" 
  shows
    "G. pG  D_generic(G)"
proof -
  note assms
  moreover from this 
  have "f``nat   P"
    by (simp add:subset_fun_image)
  moreover from calculation
  have "refl(f``nat, leq)  trans[P](leq)"
    using leq_preord unfolding preorder_on_def by (blast intro:refl_monot_domain)
  moreover from calculation 
  have "nnat.  f ` succ(n) f ` n" by (simp)
  moreover from calculation
  have "linear(f``nat, leq)"
    using leq_preord and decr_seq_linear unfolding preorder_on_def by (blast)
  moreover from calculation
  have "(pf``nat.qf``nat. compat_in(f``nat,leq,p,q))"             
    using chain_compat by (auto)
  ultimately  
  have "filter(upclosure(f``nat))" (is "filter(?G)")
    using closure_compat_filter by simp
  moreover
  have "nnat. 𝒟 ` n  ?G  0"
  proof
    fix n
    assume "nnat"
    with assms 
    have "f`succ(n)  ?G  f`succ(n)  𝒟 ` n"
      using aux_RS1 by simp
    then 
    show "𝒟 ` n  ?G  0"  by blast
  qed
  moreover from assms 
  have "p  ?G"
    using aux_RS1 by auto
  ultimately 
  show ?thesis unfolding D_generic_def by auto
qed

end (* countable_generic *)

text‹Now, the following recursive definition will fulfill the 
requirements of lemma termRS_sequence_imp_rasiowa_sikorski

consts RS_seq :: "[i,i,i,i,i,i]  i"
primrec
  "RS_seq(0,P,leq,p,enum,𝒟) = p"
  "RS_seq(succ(n),P,leq,p,enum,𝒟) = 
    enum`(μ m. enum`m, RS_seq(n,P,leq,p,enum,𝒟)  leq  enum`m  𝒟 ` n)"

context countable_generic
begin

lemma preimage_rangeD:
  assumes "fPi(A,B)" "b  range(f)" 
  shows "aA. f`a = b"
  using assms apply_equality[OF _ assms(1), of _ b] domain_type[OF _ assms(1)] by auto

lemma countable_RS_sequence_aux:
  fixes p enum
  defines "f(n)  RS_seq(n,P,leq,p,enum,𝒟)"
    and   "Q(q,k,m)  enum`m q  enum`m  𝒟 ` k"
  assumes "nnat" "pP" "P  range(enum)" "enum:natM"
    "x k. xP  knat   qP. q x  q  𝒟 ` k" 
  shows 
    "f(succ(n))  P  f(succ(n)) f(n)  f(succ(n))  𝒟 ` n"
  using nnat›
proof (induct)
  case 0
  from assms 
  obtain q where "qP" "q p" "q  𝒟 ` 0" by blast
  moreover from this and P  range(enum)
  obtain m where "mnat" "enum`m = q" 
    using preimage_rangeD[OF enum:natM] by blast
  moreover 
  have "𝒟`0  P"
    using apply_funtype[OF countable_subs_of_P] by simp
  moreover note pP
  ultimately
  show ?case 
    using LeastI[of "Q(p,0)" m] unfolding Q_def f_def by auto
next
  case (succ n)
  with assms 
  obtain q where "qP" "q f(succ(n))" "q  𝒟 ` succ(n)" by blast
  moreover from this and P  range(enum)
  obtain m where "mnat" "enum`m f(succ(n))" "enum`m  𝒟 ` succ(n)"
    using preimage_rangeD[OF enum:natM] by blast
  moreover note succ
  moreover from calculation
  have "𝒟`succ(n)  P" 
    using apply_funtype[OF countable_subs_of_P] by auto
  ultimately
  show ?case
    using LeastI[of "Q(f(succ(n)),succ(n))" m] unfolding Q_def f_def by auto
qed

lemma countable_RS_sequence:
  fixes p enum
  defines "f  λnnat. RS_seq(n,P,leq,p,enum,𝒟)"
    and   "Q(q,k,m)  enum`m q  enum`m  𝒟 ` k"
  assumes "nnat" "pP" "P  range(enum)" "enum:natM"
  shows 
    "f`0 = p" "f`succ(n) f`n  f`succ(n)  𝒟 ` n" "f`succ(n)  P"
proof -
  from assms
  show "f`0 = p" by simp
  {
    fix x k
    assume "xP" "knat"
    then
    have "qP. q x  q  𝒟 ` k"
      using seq_of_denses apply_funtype[OF countable_subs_of_P] 
      unfolding dense_def by blast
  }
  with assms
  show "f`succ(n) f`n  f`succ(n)  𝒟 ` n" "f`succ(n)P"
    unfolding f_def using countable_RS_sequence_aux by simp_all
qed

lemma RS_seq_type: 
  assumes "n  nat" "pP" "P  range(enum)" "enum:natM"
  shows "RS_seq(n,P,leq,p,enum,𝒟)  P"
  using assms countable_RS_sequence(1,3)  
  by (induct;simp) 

lemma RS_seq_funtype:
  assumes "pP" "P  range(enum)" "enum:natM"
  shows "(λnnat. RS_seq(n,P,leq,p,enum,𝒟)): nat  P"
  using assms lam_type RS_seq_type by auto

lemmas countable_rasiowa_sikorski = 
  RS_sequence_imp_rasiowa_sikorski[OF _ RS_seq_funtype countable_RS_sequence(1,2)]
end (* countable_generic *)

end

Theory Pointed_DC

section‹A pointed version of DC›
theory Pointed_DC imports ZF.AC

begin
txt‹This proof of DC is from Moschovakis "Notes on Set Theory"›

consts dc_witness :: "i  i  i  i  i  i"
primrec
  wit0   : "dc_witness(0,A,a,s,R) = a"
  witrec :"dc_witness(succ(n),A,a,s,R) = s`{xA. dc_witness(n,A,a,s,R),xR }"

lemma witness_into_A [TC]:
  assumes "aA"
    "(X . X0  XA  s`XX)"
    "yA. {xA. y,xR }  0" "nnat"
  shows "dc_witness(n, A, a, s, R)A"
  using nnat›
proof(induct n)
  case 0
  then show ?case using aA by simp
next
  case (succ x)
  then
  show ?case using assms by auto
qed

lemma witness_related :
  assumes "aA"
    "(X . X0  XA  s`XX)"
    "yA. {xA. y,xR }  0" "nnat"
  shows "dc_witness(n, A, a, s, R),dc_witness(succ(n), A, a, s, R)R"
proof -
  from assms
  have "dc_witness(n, A, a, s, R)A" (is "?x  A")
    using witness_into_A[of _ _ s R n] by simp
  with assms
  show ?thesis by auto
qed

lemma witness_funtype:
  assumes "aA"
    "(X . X0  XA  s`XX)"
    "yA. {xA. y,xR }  0"
  shows "(λnnat. dc_witness(n, A, a, s, R))  nat  A" (is "?f  _  _")
proof -
  have "?f  nat  {dc_witness(n, A, a, s, R). nnat}" (is "_  _  ?B")
    using lam_funtype assms by simp
  then
  have "?B  A"
    using witness_into_A assms by auto
  with ?f  _
  show ?thesis
    using fun_weaken_type
    by simp
qed

lemma witness_to_fun:   assumes "aA"
  "(X . X0  XA  s`XX)"
  "yA. {xA. y,xR }  0"
shows "f  natA. nnat. f`n =dc_witness(n,A,a,s,R)"
  using assms bexI[of _ "λnnat. dc_witness(n,A,a,s,R)"] witness_funtype
  by simp

theorem pointed_DC  :
  assumes "(xA. yA. x,y R)"
  shows "aA. (f  natA. f`0 = a  (n  nat. f`n,f`succ(n)R))"
proof -
  have 0:"yA. {x  A . y, x  R}  0"
    using assms by auto
  from AC_func_Pow[of A]
  obtain g
    where 1: "g  Pow(A) - {0}  A"
      "X. X  0  X  A  g ` X  X"
    by auto
  let ?f ="λa.λnnat. dc_witness(n,A,a,g,R)"
  {
    fix a
    assume "aA"
    from aA
    have f0: "?f(a)`0 = a" by simp
    with aA
    have "?f(a) ` n, ?f(a) ` succ(n)  R" if "nnat" for n
      using witness_related[OF aA 1(2) 0] beta that by simp
    then
    have "fnat  A. f ` 0 = a  (nnat. f ` n, f ` succ(n)  R)" (is "x_ .?P(x)")
      using f0 witness_funtype 0 1 a_ by blast
  }
  then show ?thesis by auto
qed

lemma aux_DC_on_AxNat2 : "xA×nat. yA. x,y,succ(snd(x))  R 
                  xA×nat. yA×nat. x,y  {a,bR. snd(b) = succ(snd(a))}"
  by (rule ballI, erule_tac x="x" in ballE, simp_all)

lemma infer_snd : "c A×B  snd(c) = k  c=fst(c),k"
  by auto

corollary DC_on_A_x_nat :
  assumes "(xA×nat. yA. x,y,succ(snd(x))  R)" "aA"
  shows "f  natA. f`0 = a  (n  nat. f`n,n,f`succ(n),succ(n)R)" (is "x_.?P(x)")
proof -
  let ?R'="{a,bR. snd(b) = succ(snd(a))}"
  from assms(1)
  have "xA×nat. yA×nat. x,y  ?R'"
    using aux_DC_on_AxNat2 by simp
  with a_
  obtain f where
    F:"fnatA×nat" "f ` 0 = a,0"  "nnat. f ` n, f ` succ(n)  ?R'"
    using pointed_DC[of "A×nat" ?R'] by blast
  let ?f="λxnat. fst(f`x)"
  from F
  have "?fnatA" "?f ` 0 = a" by auto
  have 1:"n nat  f`n= ?f`n, n" for n
  proof(induct n set:nat)
    case 0
    then show ?case using F by simp
  next
    case (succ x)
    then
    have "f`x, f`succ(x)  ?R'" "f`x  A×nat" "f`succ(x)A×nat"
      using F by simp_all
    then
    have "snd(f`succ(x)) = succ(snd(f`x))" by simp
    with succ f`x_
    show ?case using infer_snd[OF f`succ(_)_] by auto
  qed
  have "?f`n,n,?f`succ(n),succ(n)  R" if "nnat" for n
    using that 1[of "succ(n)"] 1[OF n_] F(3) by simp
  with f`0=a,0
  show ?thesis using rev_bexI[OF ?f_] by simp
qed

lemma aux_sequence_DC :
  assumes "xA. nnat. yA. x,y  S`n"
    "R={x,n,y,m  (A×nat)×(A×nat). x,yS`m }"
  shows " xA×nat . yA. x,y,succ(snd(x))  R"
  using assms Pair_fst_snd_eq by auto

lemma aux_sequence_DC2 : "xA. nnat. yA. x,y  S`n 
        xA×nat. yA. x,y,succ(snd(x))  {x,n,y,m(A×nat)×(A×nat). x,yS`m }"
  by auto

lemma sequence_DC:
  assumes "xA. nnat. yA. x,y  S`n"
  shows "aA. (f  natA. f`0 = a  (n  nat. f`n,f`succ(n)S`succ(n)))"
  by (rule ballI,insert assms,drule aux_sequence_DC2, drule DC_on_A_x_nat, auto)

end

Theory Rasiowa_Sikorski

section‹The general Rasiowa-Sikorski lemma›
theory Rasiowa_Sikorski imports Forcing_Notions Pointed_DC begin

context countable_generic
begin

lemma RS_relation:
  assumes "pP" "nnat"
  shows "yP. p,y  (λmnat. {x,yP×P. yx  y𝒟`(pred(m))})`n"
proof -
  from seq_of_denses nnat›
  have "dense(𝒟 ` pred(n))" by simp
  with pP
  have "d𝒟 ` Arith.pred(n). d p"
    unfolding dense_def by simp
  then obtain d where 3: "d  𝒟 ` Arith.pred(n)  d p"
    by blast
  from countable_subs_of_P nnat›
  have "𝒟 ` Arith.pred(n)  Pow(P)"
    by (blast dest:apply_funtype intro:pred_type)
  then 
  have "𝒟 ` Arith.pred(n)  P" 
    by (rule PowD)
  with 3
  have "d  P  d p  d  𝒟 ` Arith.pred(n)"
    by auto
  with pP nnat› 
  show ?thesis by auto
qed

lemma DC_imp_RS_sequence:
  assumes "pP"
  shows "f. f: natP  f ` 0 = p  
     (nnat. f ` succ(n) f ` n  f ` succ(n)  𝒟 ` n)"
proof -
  let ?S="(λmnat. {x,yP×P. yx  y𝒟`(pred(m))})"
  have "xP. nnat. yP. x,y  ?S`n" 
    using RS_relation by (auto)
  then
  have "aP. (f  natP. f`0 = a  (n  nat. f`n,f`succ(n)?S`succ(n)))"
    using sequence_DC by (blast)
  with pP
  show ?thesis by auto
qed
  
theorem rasiowa_sikorski:
  "pP  G. pG  D_generic(G)"
  using RS_sequence_imp_rasiowa_sikorski by (auto dest:DC_imp_RS_sequence)

end (* countable_generic *)

end

Theory Nat_Miscellanea

section‹Auxiliary results on arithmetic›
theory Nat_Miscellanea imports ZF begin

text‹Most of these results will get used at some point for the
calculation of arities.›
lemmas nat_succI =  Ord_succ_mem_iff [THEN iffD2,OF nat_into_Ord]

lemma nat_succD : "m  nat   succ(n)  succ(m)  n  m"
  by (drule_tac j="succ(m)" in ltI,auto elim:ltD)

lemmas zero_in =  ltD [OF nat_0_le]

lemma in_n_in_nat :  "m  nat  n  m  n  nat"
  by(drule ltI[of "n"],auto simp add: lt_nat_in_nat)

lemma in_succ_in_nat : "m  nat  n  succ(m)  n  nat"
  by(auto simp add:in_n_in_nat)

lemma ltI_neg : "x  nat  j  x  j  x  j < x"
  by (simp add: le_iff)

lemma succ_pred_eq  :  "m  nat  m  0   succ(pred(m)) = m"
  by (auto elim: natE)

lemma succ_ltI : "succ(j) < n  j < n"
  by (simp add: succ_leE[OF leI])

lemma succ_In : "n  nat  succ(j)  n  j  n"
  by (rule succ_ltI[THEN ltD], auto intro: ltI)

lemmas succ_leD = succ_leE[OF leI]

lemma succpred_leI : "n  nat   n  succ(pred(n))"
  by (auto elim: natE)

lemma succpred_n0 : "succ(n)  p  p0"
  by (auto)


lemma funcI : "f  A  B  a  A  b= f ` a  a, b  f"
  by(simp_all add: apply_Pair)

lemmas natEin = natE [OF lt_nat_in_nat]

lemma succ_in : "succ(x)  y   x  y"
  by (auto dest:ltD)

lemmas Un_least_lt_iffn =  Un_least_lt_iff [OF nat_into_Ord nat_into_Ord]

lemma pred_le2 : "n nat  m  nat  pred(n)  m  n  succ(m)"
  by(subgoal_tac "nnat",rule_tac n="n" in natE,auto)

lemma pred_le : "n nat  m  nat  n  succ(m)  pred(n)  m"
  by(subgoal_tac "pred(n)nat",rule_tac n="n" in natE,auto)

lemma Un_leD1 : "Ord(i) Ord(j) Ord(k)  i  j  k  i  k"   
  by (rule Un_least_lt_iff[THEN iffD1[THEN conjunct1]],simp_all)

lemma Un_leD2 : "Ord(i) Ord(j) Ord(k)  i  j k  j  k"   
  by (rule Un_least_lt_iff[THEN iffD1[THEN conjunct2]],simp_all)

lemma gt1 : "n  nat  i  n  i  0  i  1  1<i"
  by(rule_tac n="i" in natE,erule in_n_in_nat,auto intro: Ord_0_lt)

lemma pred_mono : "m  nat  n  m  pred(n)  pred(m)"
  by(rule_tac n="n" in natE,auto simp add:le_in_nat,erule_tac n="m" in natE,auto)

lemma succ_mono : "m  nat  n  m  succ(n)  succ(m)"
  by auto

lemma pred2_Un: 
  assumes "j  nat" "m  j" "n  j" 
  shows "pred(pred(m  n))  pred(pred(j))" 
  using assms pred_mono[of "j"] le_in_nat Un_least_lt pred_mono by simp

lemma nat_union_abs1 : 
  " Ord(i) ; Ord(j) ; i  j   i  j = j"
  by (rule Un_absorb1,erule le_imp_subset)

lemma nat_union_abs2 : 
  " Ord(i) ; Ord(j) ; i  j   j  i = j"
  by (rule Un_absorb2,erule le_imp_subset)

lemma nat_un_max : "Ord(i)  Ord(j)  i  j = max(i,j)"
  using max_def nat_union_abs1 not_lt_iff_le leI nat_union_abs2
  by auto

lemma nat_max_ty : "Ord(i) Ord(j)  Ord(max(i,j))"
  unfolding max_def by simp

lemma le_not_lt_nat : "Ord(p)  Ord(q)  ¬ p q  q  p" 
  by (rule ltE,rule not_le_iff_lt[THEN iffD1],auto,drule ltI[of q p],auto,erule leI)

lemmas nat_simp_union = nat_un_max nat_max_ty max_def 

lemma le_succ : "xnat  xsucc(x)" by simp
lemma le_pred : "xnat  pred(x)x" 
  using pred_le[OF _ _ le_succ] pred_succ_eq 
  by simp

lemma Un_le_compat : "o  p  q  r  Ord(o)  Ord(p)  Ord(q)  Ord(r)  o  q  p  r"
  using le_trans[of q r "pr",OF _ Un_upper2_le] le_trans[of o p "pr",OF _ Un_upper1_le]
    nat_simp_union 
  by auto

lemma Un_le : "p  r  q  r 
               Ord(p)  Ord(q)  Ord(r)  
                p  q  r"
  using nat_simp_union by auto

lemma Un_leI3 : "o  r  p  r  q  r  
                Ord(o)  Ord(p)  Ord(q)  Ord(r)  
                o  p  q  r"
  using nat_simp_union by auto

lemma diff_mono :
  assumes "m  nat" "nnat" "p  nat" "m < n" "pm"
  shows "m#-p < n#-p"
proof -
  from assms
  have "m#-p  nat" "m#-p #+p = m"
    using add_diff_inverse2 by simp_all
  with assms
  show ?thesis
    using less_diff_conv[of n p "m #- p",THEN iffD2] by simp
qed

lemma pred_Un:
  "x  nat  y  nat  Arith.pred(succ(x)  y) = x  Arith.pred(y)"
  "x  nat  y  nat  Arith.pred(x  succ(y)) = Arith.pred(x)  y"
  using pred_Un_distrib pred_succ_eq by simp_all

lemma le_natI : "j  n  n  nat  jnat"
  by(drule ltD,rule in_n_in_nat,rule nat_succ_iff[THEN iffD2,of n],simp_all)

lemma le_natE : "nnat  j < n   jn"
  by(rule ltE[of j n],simp+)

lemma diff_cancel :
  assumes "m  nat" "nnat" "m < n"
  shows "m#-n = 0"
  using assms diff_is_0_lemma leI by simp

lemma leD : assumes "nnat" "j  n"
  shows "j < n | j = n"
  using leE[OF jn,of "j<n | j = n"] by auto

subsection‹Some results in ordinal arithmetic›
text‹The following results are auxiliary to the proof of 
wellfoundedness of the relation termfrecR

lemma max_cong :
  assumes "x  y" "Ord(y)" "Ord(z)" shows "max(x,y)  max(y,z)"
  using assms 
proof (cases "y  z")
  case True
  then show ?thesis 
    unfolding max_def using assms by simp
next
  case False
  then have "z  y"  using assms not_le_iff_lt leI by simp
  then show ?thesis 
    unfolding max_def using assms by simp 
qed

lemma max_commutes : 
  assumes "Ord(x)" "Ord(y)"
  shows "max(x,y) = max(y,x)"
  using assms Un_commute nat_simp_union(1) nat_simp_union(1)[symmetric] by auto

lemma max_cong2 :
  assumes "x  y" "Ord(y)" "Ord(z)" "Ord(x)" 
  shows "max(x,z)  max(y,z)"
proof -
  from assms 
  have " x  z  y  z"
    using lt_Ord Ord_Un Un_mono[OF  le_imp_subset[OF xy]]  subset_imp_le by auto
  then show ?thesis 
    using  nat_simp_union ‹Ord(x) ‹Ord(z) ‹Ord(y) by simp
qed

lemma max_D1 :
  assumes "x = y" "w < z"  "Ord(x)"  "Ord(w)" "Ord(z)" "max(x,w) = max(y,z)"
  shows "zy"
proof -
  from assms
  have "w <  x  w" using Un_upper2_lt[OF w<z] assms nat_simp_union by simp
  then
  have "w < x" using assms lt_Un_iff[of x w w] lt_not_refl by auto
  then 
  have "y = y  z" using assms max_commutes nat_simp_union assms leI by simp 
  then 
  show ?thesis using Un_leD2 assms by simp
qed

lemma max_D2 :
  assumes "w = y  w = z" "x < y"  "Ord(x)"  "Ord(w)" "Ord(y)" "Ord(z)" "max(x,w) = max(y,z)"
  shows "x<w"
proof -
  from assms
  have "x < z  y" using Un_upper2_lt[OF x<y] by simp
  then
  consider (a) "x < y" | (b) "x < w"
    using assms nat_simp_union by simp
  then show ?thesis proof (cases)
    case a
    consider (c) "w = y" | (d) "w = z" 
      using assms by auto
    then show ?thesis proof (cases)
      case c
      with a show ?thesis by simp
    next
      case d
      with a
      show ?thesis 
      proof (cases "y <w")
        case True       
        then show ?thesis using lt_trans[OF x<y] by simp
      next
        case False
        then
        have "w  y" 
          using not_lt_iff_le[OF assms(5) assms(4)] by simp
        with w=z
        have "max(z,y) = y"  unfolding max_def using assms by simp
        with assms
        have "... = x  w" using nat_simp_union max_commutes  by simp
        then show ?thesis using le_Un_iff assms by blast
      qed
    qed
  next
    case b
    then show ?thesis .
  qed
qed

lemma oadd_lt_mono2 :
  assumes  "Ord(n)" "Ord(α)" "Ord(β)" "α < β" "x < n" "y < n" "0 <n"
  shows "n ** α ++ x < n **β ++ y"
proof -
  consider (0) "β=0" | (s) γ where  "Ord(γ)" "β = succ(γ)" | (l) "Limit(β)"
    using Ord_cases[OF ‹Ord(β),of ?thesis] by force
  then show ?thesis 
  proof cases
    case 0
    then show ?thesis using α<β by auto
  next
    case s
    then
    have "αγ" using α<β using leI by auto
    then
    have "n ** α  n ** γ" using omult_le_mono[OF _ αγ] ‹Ord(n) by simp
    then
    have "n ** α ++ x < n ** γ ++ n" using oadd_lt_mono[OF _ x<n] by simp
    also
    have "... = n ** β" using β=succ(_) omult_succ ‹Ord(β) ‹Ord(n) by simp
    finally
    have "n ** α ++ x < n ** β" by auto
    then
    show ?thesis using oadd_le_self ‹Ord(β) lt_trans2 ‹Ord(n) by auto
  next
    case l
    have "Ord(x)" using x<n lt_Ord by simp
    with l
    have "succ(α) < β" using Limit_has_succ α<β by simp
    have "n ** α ++ x < n ** α ++ n" 
      using oadd_lt_mono[OF le_refl[OF Ord_omult[OF _ ‹Ord(α)]] x<n] ‹Ord(n) by simp
    also
    have "... = n ** succ(α)" using omult_succ ‹Ord(α) ‹Ord(n) by simp
    finally
    have "n ** α ++ x < n ** succ(α)" by simp 
    with ‹succ(α) < β
    have "n ** α ++ x < n ** β" using lt_trans omult_lt_mono ‹Ord(n) 0<n  by auto      
    then show ?thesis using oadd_le_self ‹Ord(β) lt_trans2 ‹Ord(n) by auto
  qed
qed
end

Theory Internalizations

section‹Aids to internalize formulas›
theory Internalizations
  imports 
    "ZF-Constructible.DPow_absolute" 
begin

text‹We found it useful to have slightly different versions of some 
results in ZF-Constructible:›
lemma nth_closed :
  assumes "0A" "envlist(A)"
  shows "nth(n,env)A" 
  using assms(2,1) unfolding nth_def by (induct env; simp)

lemmas FOL_sats_iff = sats_Nand_iff sats_Forall_iff sats_Neg_iff sats_And_iff
  sats_Or_iff sats_Implies_iff sats_Iff_iff sats_Exists_iff 

lemma nth_ConsI: "nth(n,l) = x; n  nat  nth(succ(n), Cons(a,l)) = x"
by simp

lemmas nth_rules = nth_0 nth_ConsI nat_0I nat_succI
lemmas sep_rules = nth_0 nth_ConsI FOL_iff_sats function_iff_sats
                   fun_plus_iff_sats successor_iff_sats
                    omega_iff_sats FOL_sats_iff Replace_iff_sats

text‹Also a different compilation of lemmas (termsep_rules›) used in formula
 synthesis›
lemmas fm_defs = omega_fm_def limit_ordinal_fm_def empty_fm_def typed_function_fm_def
                 pair_fm_def upair_fm_def domain_fm_def function_fm_def succ_fm_def
                 cons_fm_def fun_apply_fm_def image_fm_def big_union_fm_def union_fm_def
                 relation_fm_def composition_fm_def field_fm_def ordinal_fm_def range_fm_def
                 transset_fm_def subset_fm_def Replace_fm_def


end

Theory Recursion_Thms

section‹Some enhanced theorems on recursion›

theory Recursion_Thms imports ZF.Epsilon begin

text‹We prove results concerning definitions by well-founded
recursion on some relation termR and its transitive closure
termR^*
  (* Restrict the relation r to the field A*A *)

lemma fld_restrict_eq : "a  A  (r  A×A)-``{a} = (r-``{a}  A)"
  by(force)

lemma fld_restrict_mono : "relation(r)  A  B  r  A×A  r  B×B"
  by(auto)

lemma fld_restrict_dom :
  assumes "relation(r)" "domain(r)  A" "range(r) A"
  shows "r A×A = r"
proof (rule equalityI,blast,rule subsetI)
  { fix x
    assume xr: "x  r"
    from xr assms have " a b . x = a,b" by (simp add: relation_def)
    then obtain a b where "a,b  r" "a,b  rA×A" "x  rA×A"
      using assms xr
      by force
    then have "x r  A×A" by simp
  }
  then show "x  r  x rA×A" for x .
qed

definition tr_down :: "[i,i]  i"
  where "tr_down(r,a) = (r^+)-``{a}"

lemma tr_downD : "x  tr_down(r,a)  x,a  r^+"
  by (simp add: tr_down_def vimage_singleton_iff)

lemma pred_down : "relation(r)  r-``{a}  tr_down(r,a)"
  by(simp add: tr_down_def vimage_mono r_subset_trancl)

lemma tr_down_mono : "relation(r)  x  r-``{a}  tr_down(r,x)  tr_down(r,a)"
  by(rule subsetI,simp add:tr_down_def,auto dest: underD,force simp add: underI r_into_trancl trancl_trans)

lemma rest_eq :
  assumes "relation(r)" and "r-``{a}  B" and "a  B"
  shows "r-``{a} = (rB×B)-``{a}"
proof (intro equalityI subsetI)
  fix x
  assume "x  r-``{a}"
  then
  have "x  B" using assms by (simp add: subsetD)
  from x r-``{a}
  have "x,a  r" using underD by simp
  then
  show "x  (rB×B)-``{a}" using xB aB underI by simp
next
  from assms
  show "x  r -`` {a}" if  "x  (r  B×B) -`` {a}" for x
    using vimage_mono that by auto
qed

lemma wfrec_restr_eq : "r' = r  A×A  wfrec[A](r,a,H) = wfrec(r',a,H)"
  by(simp add:wfrec_on_def)

lemma wfrec_restr :
  assumes rr: "relation(r)" and wfr:"wf(r)"
  shows  "a  A  tr_down(r,a)  A  wfrec(r,a,H) = wfrec[A](r,a,H)"
proof (induct a arbitrary:A rule:wf_induct_raw[OF wfr] )
  case (1 a)
  have wfRa : "wf[A](r)"
    using wf_subset wfr wf_on_def Int_lower1 by simp
  from pred_down rr
  have "r -`` {a}  tr_down(r, a)" .
  with 1
  have "r-``{a}  A" by (force simp add: subset_trans)
  {
    fix x
    assume x_a : "x  r-``{a}"
    with r-``{a}  A
    have "x  A" ..
    from pred_down rr
    have b : "r -``{x}  tr_down(r,x)" .
    then
    have "tr_down(r,x)  tr_down(r,a)"
      using tr_down_mono x_a rr by simp
    with 1
    have "tr_down(r,x)  A" using subset_trans by force
    have "x,a  r" using x_a  underD by simp
    with 1 ‹tr_down(r,x)  A x  A
    have "wfrec(r,x,H) = wfrec[A](r,x,H)" by simp
  }
  then
  have "x r-``{a}  wfrec(r,x,H) =  wfrec[A](r,x,H)" for x  .
  then
  have Eq1 :"(λ x  r-``{a} . wfrec(r,x,H)) = (λ x  r-``{a} . wfrec[A](r,x,H))"
    using lam_cong by simp

  from assms
  have "wfrec(r,a,H) = H(a,λ x  r-``{a} . wfrec(r,x,H))" by (simp add:wfrec)
  also
  have "... = H(a,λ x  r-``{a} . wfrec[A](r,x,H))"
    using assms Eq1 by simp
  also from 1 r-``{a}  A
  have "... = H(a,λ x  (rA×A)-``{a} . wfrec[A](r,x,H))"
    using assms rest_eq  by simp
  also from aA
  have "... = H(a,λ x  (r-``{a})A . wfrec[A](r,x,H))"
    using fld_restrict_eq by simp
  also from aA wf[A](r)
  have "... = wfrec[A](r,a,H)" using wfrec_on by simp
  finally show ?case .
qed

lemmas wfrec_tr_down = wfrec_restr[OF _ _ _ subset_refl]

lemma wfrec_trans_restr : "relation(r)  wf(r)  trans(r)  r-``{a}A  a  A 
  wfrec(r, a, H) = wfrec[A](r, a, H)"
  by(subgoal_tac "tr_down(r,a)  A",auto simp add : wfrec_restr tr_down_def trancl_eq_r)


lemma field_trancl : "field(r^+) = field(r)"
  by (blast intro: r_into_trancl dest!: trancl_type [THEN subsetD])

definition
  Rrel :: "[iio,i]  i" where
  "Rrel(R,A)  {zA×A. x y. z = x, y  R(x,y)}"

lemma RrelI : "x  A  y  A  R(x,y)  x,y  Rrel(R,A)"
  unfolding Rrel_def by simp

lemma Rrel_mem: "Rrel(mem,x) = Memrel(x)"
  unfolding Rrel_def Memrel_def ..

lemma relation_Rrel: "relation(Rrel(R,d))"
  unfolding Rrel_def relation_def by simp

lemma field_Rrel: "field(Rrel(R,d))   d"
  unfolding Rrel_def by auto

lemma Rrel_mono : "A  B  Rrel(R,A)  Rrel(R,B)"
  unfolding Rrel_def by blast

lemma Rrel_restr_eq : "Rrel(R,A)  B×B = Rrel(R,AB)"
  unfolding Rrel_def by blast

(* now a consequence of the previous lemmas *)
lemma field_Memrel : "field(Memrel(A))  A"
  (* unfolding field_def using Ordinal.Memrel_type by blast *)
  using Rrel_mem field_Rrel by blast

lemma restrict_trancl_Rrel:
  assumes "R(w,y)"
  shows "restrict(f,Rrel(R,d)-``{y})`w
       = restrict(f,(Rrel(R,d)^+)-``{y})`w"
proof (cases "yd")
  let ?r="Rrel(R,d)" and ?s="(Rrel(R,d))^+"
  case True
  show ?thesis
  proof (cases "wd")
    case True
    with yd assms
    have "w,y?r"
      unfolding Rrel_def by blast
    then
    have "w,y?s"
      using r_subset_trancl[of ?r] relation_Rrel[of R d] by blast
    with w,y?r
    have "w?r-``{y}" "w?s-``{y}"
      using vimage_singleton_iff by simp_all
    then
    show ?thesis by simp
  next
    case False
    then
    have "wdomain(restrict(f,?r-``{y}))"
      using subsetD[OF field_Rrel[of R d]] by auto
    moreover from wd
    have "wdomain(restrict(f,?s-``{y}))"
      using subsetD[OF field_Rrel[of R d], of w] field_trancl[of ?r]
        fieldI1[of w y ?s] by auto
    ultimately
    have "restrict(f,?r-``{y})`w = 0" "restrict(f,?s-``{y})`w = 0"
      unfolding apply_def by auto
    then show ?thesis by simp
  qed
next
  let ?r="Rrel(R,d)"
  let ?s="?r^+"
  case False
  then
  have "?r-``{y}=0"
    unfolding Rrel_def by blast
  then
  have "w?r-``{y}" by simp
  with yd assms
  have "yfield(?s)"
    using field_trancl subsetD[OF field_Rrel[of R d]] by force
  then
  have "w?s-``{y}"
    using vimage_singleton_iff by blast
  with w?r-``{y}
  show ?thesis by simp
qed

lemma restrict_trans_eq:
  assumes "w  y"
  shows "restrict(f,Memrel(eclose({x}))-``{y})`w
       = restrict(f,(Memrel(eclose({x}))^+)-``{y})`w"
  using assms restrict_trancl_Rrel[of mem ] Rrel_mem by (simp)

lemma wf_eq_trancl:
  assumes " f y . H(y,restrict(f,R-``{y})) = H(y,restrict(f,R^+-``{y}))"
  shows  "wfrec(R, x, H) = wfrec(R^+, x, H)" (is "wfrec(?r,_,_) = wfrec(?r',_,_)")
proof -
  have "wfrec(R, x, H) = wftrec(?r^+, x, λy f. H(y, restrict(f,?r-``{y})))"
    unfolding wfrec_def ..
  also
  have " ... = wftrec(?r^+, x, λy f. H(y, restrict(f,(?r^+)-``{y})))"
    using assms by simp
  also
  have " ... =  wfrec(?r^+, x, H)"
    unfolding wfrec_def using trancl_eq_r[OF relation_trancl trans_trancl] by simp
  finally
  show ?thesis .
qed

end

Theory Relative_Univ

section‹Relativization of the cumulative hierarchy›
theory Relative_Univ
  imports
    "ZF-Constructible.Rank"
    Internalizations
    Recursion_Thms

begin

lemma (in M_trivial) powerset_abs' [simp]: 
  assumes
    "M(x)" "M(y)"
  shows
    "powerset(M,x,y)  y = {aPow(x) . M(a)}"
  using powerset_abs assms by simp

lemma Collect_inter_Transset:
  assumes 
    "Transset(M)" "b  M"
  shows
    "{xb . P(x)} = {xb . P(x)}  M"
    using assms unfolding Transset_def
  by (auto)  

lemma (in M_trivial) family_union_closed: "strong_replacement(M, λx y. y = f(x)); M(A); xA. M(f(x))
       M(xA. f(x))"
  using RepFun_closed ..

(* "Vfrom(A,i) ≡ transrec(i, %x f. A ∪ (⋃y∈x. Pow(f`y)))" *)
(* HVfrom is *not* the recursive step for Vfrom. It is the
   relativized version *)
definition
  HVfrom :: "[io,i,i,i]  i" where
  "HVfrom(M,A,x,f)  A  (yx. {aPow(f`y). M(a)})"

(* z = Pow(f`y) *)
definition
  is_powapply :: "[io,i,i,i]  o" where
  "is_powapply(M,f,y,z)  M(z)  (fy[M]. fun_apply(M,f,y,fy)  powerset(M,fy,z))"

(* Trivial lemma *)
lemma is_powapply_closed: "is_powapply(M,f,y,z)  M(z)"
  unfolding is_powapply_def by simp

(* is_Replace(M,A,P,z) ≡ ∀u[M]. u ∈ z ⟷ (∃x[M]. x∈A & P(x,u)) *)
definition
  is_HVfrom :: "[io,i,i,i,i]  o" where
  "is_HVfrom(M,A,x,f,h)  U[M]. R[M].  union(M,A,U,h) 
         big_union(M,R,U)  is_Replace(M,x,is_powapply(M,f),R)" 


definition
  is_Vfrom :: "[io,i,i,i]  o" where
  "is_Vfrom(M,A,i,V)  is_transrec(M,is_HVfrom(M,A),i,V)"

definition
  is_Vset :: "[io,i,i]  o" where
  "is_Vset(M,i,V)  z[M]. empty(M,z)  is_Vfrom(M,z,i,V)"


subsection‹Formula synthesis›

schematic_goal sats_is_powapply_fm_auto:
  assumes
    "fnat" "ynat" "znat" "envlist(A)" "0A"
  shows
    "is_powapply(##A,nth(f, env),nth(y, env),nth(z, env))
     sats(A,?ipa_fm(f,y,z),env)"
  unfolding is_powapply_def is_Collect_def powerset_def subset_def
  using nth_closed assms
   by (simp) (rule sep_rules  | simp)+

schematic_goal is_powapply_iff_sats:
  assumes
    "nth(f,env) = ff" "nth(y,env) = yy" "nth(z,env) = zz" "0A"
    "f  nat"  "y  nat" "z  nat" "env  list(A)"
  shows
       "is_powapply(##A,ff,yy,zz)  sats(A, ?is_one_fm(a,r), env)"
  unfolding ‹nth(f,env) = ff[symmetric] ‹nth(y,env) = yy[symmetric]
    ‹nth(z,env) = zz[symmetric]
  by (rule sats_is_powapply_fm_auto(1); simp add:assms)

(* rank *)
definition
  Hrank :: "[i,i]  i" where
  "Hrank(x,f) = (yx. succ(f`y))"

definition
  PHrank :: "[io,i,i,i]  o" where
  "PHrank(M,f,y,z)  M(z)  (fy[M]. fun_apply(M,f,y,fy)  successor(M,fy,z))"

definition
  is_Hrank :: "[io,i,i,i]  o" where
  "is_Hrank(M,x,f,hc)  (R[M]. big_union(M,R,hc) is_Replace(M,x,PHrank(M,f),R)) "

definition
  rrank :: "i  i" where
  "rrank(a)  Memrel(eclose({a}))^+" 

lemma (in M_eclose) wf_rrank : "M(x)  wf(rrank(x))" 
  unfolding rrank_def using wf_trancl[OF wf_Memrel] .

lemma (in M_eclose) trans_rrank : "M(x)  trans(rrank(x))"
  unfolding rrank_def using trans_trancl .

lemma (in M_eclose) relation_rrank : "M(x)  relation(rrank(x))" 
  unfolding rrank_def using relation_trancl .

lemma (in M_eclose) rrank_in_M : "M(x)  M(rrank(x))" 
  unfolding rrank_def by simp


subsection‹Absoluteness results›

locale M_eclose_pow = M_eclose + 
  assumes
    power_ax : "power_ax(M)" and
    powapply_replacement : "M(f)  strong_replacement(M,is_powapply(M,f))" and
    HVfrom_replacement : " M(i) ; M(A)   
                          transrec_replacement(M,is_HVfrom(M,A),i)" and
    PHrank_replacement : "M(f)  strong_replacement(M,PHrank(M,f))" and
    is_Hrank_replacement : "M(x)  wfrec_replacement(M,is_Hrank(M),rrank(x))"

begin

lemma is_powapply_abs: "M(f); M(y)  is_powapply(M,f,y,z)  M(z)  z = {xPow(f`y). M(x)}"
  unfolding is_powapply_def by simp

lemma "M(A); M(x); M(f); M(h)   
      is_HVfrom(M,A,x,f,h)  
      (R[M]. h = A  R  is_Replace(M, x,λx y. y = {x  Pow(f ` x) . M(x)}, R))"
  using is_powapply_abs unfolding is_HVfrom_def by auto

lemma Replace_is_powapply:
  assumes
    "M(R)" "M(A)" "M(f)" 
  shows
  "is_Replace(M, A, is_powapply(M, f), R)  R = Replace(A,is_powapply(M,f))"
proof -
  have "univalent(M,A,is_powapply(M,f))" 
    using M(A) M(f) unfolding univalent_def is_powapply_def by simp
  moreover
  have "x y.  xA; is_powapply(M,f,x,y)   M(y)"
    using M(A) M(f) unfolding is_powapply_def by simp
  ultimately
  show ?thesis using M(A) M(R) Replace_abs by simp
qed

lemma powapply_closed:
  " M(y) ; M(f)   M({x  Pow(f ` y) . M(x)})"
  using apply_closed power_ax unfolding power_ax_def by simp

lemma RepFun_is_powapply:
  assumes
    "M(R)" "M(A)" "M(f)" 
  shows
  "Replace(A,is_powapply(M,f)) = RepFun(A,λy.{xPow(f`y). M(x)})"
proof -
  have "{y . x  A, M(y)  y = {x  Pow(f ` x) . M(x)}} = {y . x  A, y = {x  Pow(f ` x) . M(x)}}"
    using assms powapply_closed transM[of _ A] by blast
  also
  have " ... = {{x  Pow(f ` y) . M(x)} . y  A}" by auto
  finally 
  show ?thesis using assms is_powapply_abs transM[of _ A] by simp
qed

lemma RepFun_powapply_closed:
  assumes 
    "M(f)" "M(A)"
  shows 
    "M(Replace(A,is_powapply(M,f)))"
proof -
  have "univalent(M,A,is_powapply(M,f))" 
    using M(A) M(f) unfolding univalent_def is_powapply_def by simp
  moreover
  have " xA ; is_powapply(M,f,x,y)   M(y)" for x y
    using assms unfolding is_powapply_def by simp
  ultimately
  show ?thesis using assms powapply_replacement by simp
qed

lemma Union_powapply_closed:
  assumes 
    "M(x)" "M(f)"
  shows 
    "M(yx. {aPow(f`y). M(a)})"
proof -
  have "M({aPow(f`y). M(a)})" if "yx" for y
    using that assms transM[of _ x] powapply_closed by simp
  then
  have "M({{aPow(f`y). M(a)}. yx})"
    using assms transM[of _ x]  RepFun_powapply_closed RepFun_is_powapply by simp
  then show ?thesis using assms by simp
qed

lemma relation2_HVfrom: "M(A)  relation2(M,is_HVfrom(M,A),HVfrom(M,A))"
    unfolding is_HVfrom_def HVfrom_def relation2_def
    using Replace_is_powapply RepFun_is_powapply 
          Union_powapply_closed RepFun_powapply_closed by auto

lemma HVfrom_closed : 
  "M(A)  x[M]. g[M]. function(g)  M(HVfrom(M,A,x,g))"
  unfolding HVfrom_def using Union_powapply_closed by simp

lemma transrec_HVfrom:
  assumes "M(A)"
  shows "Ord(i)  {xVfrom(A,i). M(x)} = transrec(i,HVfrom(M,A))"
proof (induct rule:trans_induct)
  case (step i)
  have "Vfrom(A,i) = A  (yi. Pow((λxi. Vfrom(A, x)) ` y))"
    using def_transrec[OF Vfrom_def, of A i] by simp
  then 
  have "Vfrom(A,i) = A  (yi. Pow(Vfrom(A, y)))"
    by simp
  then
  have "{xVfrom(A,i). M(x)} = {xA. M(x)}  (yi. {xPow(Vfrom(A, y)). M(x)})"
    by auto
  with M(A)
  have "{xVfrom(A,i). M(x)} = A  (yi. {xPow(Vfrom(A, y)). M(x)})" 
    by (auto intro:transM)
  also
  have "... = A  (yi. {xPow({zVfrom(A,y). M(z)}). M(x)})" 
  proof -
    have "{xPow(Vfrom(A, y)). M(x)} = {xPow({zVfrom(A,y). M(z)}). M(x)}"
      if "yi" for y by (auto intro:transM)
    then
    show ?thesis by simp
  qed
  also from step 
  have " ... = A  (yi. {xPow(transrec(y, HVfrom(M, A))). M(x)})" by auto
  also
  have " ... = transrec(i, HVfrom(M, A))"
    using def_transrec[of "λy. transrec(y, HVfrom(M, A))" "HVfrom(M, A)" i,symmetric] 
    unfolding HVfrom_def by simp
  finally
  show ?case .
qed

lemma Vfrom_abs: " M(A); M(i); M(V); Ord(i)   is_Vfrom(M,A,i,V)  V = {xVfrom(A,i). M(x)}"
  unfolding is_Vfrom_def
  using relation2_HVfrom HVfrom_closed HVfrom_replacement 
    transrec_abs[of "is_HVfrom(M,A)" i "HVfrom(M,A)"] transrec_HVfrom by simp

lemma Vfrom_closed: " M(A); M(i); Ord(i)   M({xVfrom(A,i). M(x)})"
  unfolding is_Vfrom_def
  using relation2_HVfrom HVfrom_closed HVfrom_replacement 
    transrec_closed[of "is_HVfrom(M,A)" i "HVfrom(M,A)"] transrec_HVfrom by simp

lemma Vset_abs: " M(i); M(V); Ord(i)   is_Vset(M,i,V)  V = {xVset(i). M(x)}"
  using Vfrom_abs unfolding is_Vset_def by simp

lemma Vset_closed: " M(i); Ord(i)   M({xVset(i). M(x)})"
  using Vfrom_closed unfolding is_Vset_def by simp

lemma Hrank_trancl:"Hrank(y, restrict(f,Memrel(eclose({x}))-``{y}))
                  = Hrank(y, restrict(f,(Memrel(eclose({x}))^+)-``{y}))"
  unfolding Hrank_def
  using restrict_trans_eq by simp

lemma rank_trancl: "rank(x) = wfrec(rrank(x), x, Hrank)"
proof -
  have "rank(x) =  wfrec(Memrel(eclose({x})), x, Hrank)"
    (is "_ = wfrec(?r,_,_)")
    unfolding rank_def transrec_def Hrank_def by simp
  also
  have " ... = wftrec(?r^+, x, λy f. Hrank(y, restrict(f,?r-``{y})))"
    unfolding wfrec_def ..
  also
  have " ... = wftrec(?r^+, x, λy f. Hrank(y, restrict(f,(?r^+)-``{y})))"
    using Hrank_trancl by simp
  also
  have " ... =  wfrec(?r^+, x, Hrank)"
    unfolding wfrec_def using trancl_eq_r[OF relation_trancl trans_trancl] by simp
  finally
  show ?thesis unfolding rrank_def .
qed

lemma univ_PHrank : " M(z) ; M(f)   univalent(M,z,PHrank(M,f))" 
  unfolding univalent_def PHrank_def by simp


lemma PHrank_abs :
    " M(f) ; M(y)   PHrank(M,f,y,z)  M(z)  z = succ(f`y)"
  unfolding PHrank_def by simp

lemma PHrank_closed : "PHrank(M,f,y,z)  M(z)" 
  unfolding PHrank_def by simp

lemma Replace_PHrank_abs:
  assumes
    "M(z)" "M(f)" "M(hr)" 
  shows
    "is_Replace(M,z,PHrank(M,f),hr)  hr = Replace(z,PHrank(M,f))" 
proof -
  have "x y. xz; PHrank(M,f,x,y)   M(y)"
    using M(z) M(f) unfolding PHrank_def by simp
  then
  show ?thesis using M(z) M(hr) M(f) univ_PHrank Replace_abs by simp
qed

lemma RepFun_PHrank:
  assumes
    "M(R)" "M(A)" "M(f)" 
  shows
  "Replace(A,PHrank(M,f)) = RepFun(A,λy. succ(f`y))"
proof -
  have "{z . y  A, M(z)  z = succ(f`y)} = {z . y  A, z = succ(f`y)}" 
    using assms PHrank_closed transM[of _ A] by blast
  also
  have " ... = {succ(f`y) . y  A}" by auto
  finally 
  show ?thesis using assms PHrank_abs transM[of _ A] by simp
qed

lemma RepFun_PHrank_closed :
  assumes
    "M(f)" "M(A)" 
  shows
    "M(Replace(A,PHrank(M,f)))"
proof -
  have " xA ; PHrank(M,f,x,y)   M(y)" for x y
    using assms unfolding PHrank_def by simp
  with univ_PHrank
  show ?thesis using assms PHrank_replacement by simp
qed

lemma relation2_Hrank :
  "relation2(M,is_Hrank(M),Hrank)"
  unfolding is_Hrank_def Hrank_def relation2_def
  using Replace_PHrank_abs RepFun_PHrank RepFun_PHrank_closed by auto


lemma Union_PHrank_closed:
  assumes 
    "M(x)" "M(f)"
  shows 
    "M(yx. succ(f`y))"
proof -
  have "M(succ(f`y))" if "yx" for y
    using that assms transM[of _ x] by simp
  then
  have "M({succ(f`y). yx})"
    using assms transM[of _ x]  RepFun_PHrank_closed RepFun_PHrank by simp
  then show ?thesis using assms by simp
qed

lemma is_Hrank_closed : 
  "M(A)  x[M]. g[M]. function(g)  M(Hrank(x,g))"
  unfolding Hrank_def using RepFun_PHrank_closed Union_PHrank_closed by simp

lemma rank_closed: "M(a)  M(rank(a))"
  unfolding rank_trancl 
  using relation2_Hrank is_Hrank_closed is_Hrank_replacement 
        wf_rrank relation_rrank trans_rrank rrank_in_M 
         trans_wfrec_closed[of "rrank(a)" a "is_Hrank(M)"] by simp


lemma M_into_Vset:
  assumes "M(a)"
  shows "i[M]. V[M]. ordinal(M,i)  is_Vfrom(M,0,i,V)  aV"
proof -
  let ?i="succ(rank(a))"
  from assms
  have "a{xVfrom(0,?i). M(x)}" (is "a?V")
    using Vset_Ord_rank_iff by simp
  moreover from assms
  have "M(?i)"
    using rank_closed by simp
  moreover 
  note M(a)
  moreover from calculation
  have "M(?V)"
    using Vfrom_closed by simp
  moreover from calculation
  have "ordinal(M,?i)  is_Vfrom(M, 0, ?i, ?V)  a  ?V"
    using Ord_rank Vfrom_abs by simp 
  ultimately
  show ?thesis by blast
qed

end
end

Theory Synthetic_Definition

section‹Automatic synthesis of formulas›

theory Synthetic_Definition
  imports Utils
  keywords "synthesize" :: thy_decl % "ML"
    and "synthesize_notc" :: thy_decl % "ML"
    and "from_schematic"
begin

MLval $` = curry ((op $) o swap)
infix $`

fun pair f g x = (f x, g x)

fun display kind pos (thms,thy) =
  let val _ = Proof_Display.print_results true pos thy ((kind,""),[thms])
  in thy
end

fun prove_tc_form goal thms ctxt =
  Goal.prove ctxt [] [] goal
     (fn _ => rewrite_goal_tac ctxt thms 1
              THEN TypeCheck.typecheck_tac ctxt)

fun prove_sats goal thms thm_auto ctxt =
  let val ctxt' = ctxt |> Simplifier.add_simp (thm_auto |> hd)
  in
  Goal.prove ctxt [] [] goal
     (fn _ => rewrite_goal_tac ctxt thms 1
              THEN PARALLEL_ALLGOALS (asm_simp_tac ctxt')
              THEN TypeCheck.typecheck_tac ctxt')
  end

fun is_mem (@{const mem} $ _ $  _) = true
  | is_mem _ = false

fun synth_thm_sats def_name term lhs set env hyps vars vs pos thm_auto lthy =
let val (_,tm,ctxt1) = Utils.thm_concl_tm lthy term
    val (thm_refs,ctxt2) = Variable.import true [Proof_Context.get_thm lthy term] ctxt1 |>> #2
    val vs' = map (Thm.term_of o #2) vs
    val vars' = map (Thm.term_of o #2) vars
    val r_tm = tm |> Utils.dest_lhs_def |> fold (op $`) vs'
    val sats = @{const apply} $ (@{const satisfies} $ set $ r_tm) $ env
    val rhs = @{const IFOL.eq(i)} $ sats $ (@{const succ} $ @{const zero})
    val concl = @{const IFOL.iff} $ lhs $ rhs
    val g_iff = Logic.list_implies(hyps, Utils.tp concl)
    val thm = prove_sats g_iff thm_refs thm_auto ctxt2
    val name = Binding.name (def_name ^ "_iff_sats")
    val thm = Utils.fix_vars thm (map (#1 o dest_Free) vars') lthy
 in
   Local_Theory.note ((name, []), [thm]) lthy |> display "theorem" pos
 end

fun synth_thm_tc def_name term hyps vars pos lthy =
let val (_,tm,ctxt1) = Utils.thm_concl_tm lthy term
    val (thm_refs,ctxt2) = Variable.import true [Proof_Context.get_thm lthy term] ctxt1
                    |>> #2
    val vars' = map (Thm.term_of o #2) vars
    val tc_attrib = @{attributes [TC]}
    val r_tm = tm |> Utils.dest_lhs_def |> fold (op $`) vars'
    val concl = @{const mem} $ r_tm $ @{const formula}
    val g = Logic.list_implies(hyps, Utils.tp concl)
    val thm = prove_tc_form g thm_refs ctxt2
    val name = Binding.name (def_name ^ "_type")
    val thm = Utils.fix_vars thm (map (#1 o dest_Free) vars') ctxt2
 in
   Local_Theory.note ((name, tc_attrib), [thm]) lthy |> display "theorem" pos
 end


fun synthetic_def def_name thmref pos tc auto thy =
  let
    val (thm_ref,_) = thmref |>> Facts.ref_name
    val (((_,vars),thm_tms),_) = Variable.import true [Proof_Context.get_thm thy thm_ref] thy
    val (tm,hyps) = thm_tms |> hd |> pair Thm.concl_of Thm.prems_of
    val (lhs,rhs) = tm |> Utils.dest_iff_tms o Utils.dest_trueprop
    val ((set,t),env) = rhs |> Utils.dest_sats_frm
    fun olist t = Ord_List.make String.compare (Term.add_free_names t [])
    fun relevant ts (@{const mem} $ t $ _) = not (Term.is_Free t) orelse
        Ord_List.member String.compare ts (t |> Term.dest_Free |> #1)
      | relevant _ _ = false
    val t_vars = olist t
    val vs = List.filter (fn (((v,_),_),_) => Utils.inList v t_vars) vars
    val at = List.foldr (fn ((_,var),t') => lambda (Thm.term_of var) t') t vs
    val hyps' = List.filter (relevant t_vars o Utils.dest_trueprop) hyps
  in
    Local_Theory.define ((Binding.name def_name, NoSyn),
                        ((Binding.name (def_name ^ "_def"), []), at)) thy |> #2 |>
    (if tc then synth_thm_tc def_name (def_name ^ "_def") hyps' vs pos else I) |>
    (if auto then synth_thm_sats def_name (def_name ^ "_def") lhs set env hyps vars vs pos thm_tms else I)

end
MLlocal
  val synth_constdecl =
       Parse.position (Parse.string -- ((Parse.$$$ "from_schematic" |-- Parse.thm)));

  val _ =
     Outer_Syntax.local_theory command_keywordsynthesize "ML setup for synthetic definitions"
       (synth_constdecl >> (fn ((bndg,thm),p) => synthetic_def bndg thm p true true))

  val _ =
     Outer_Syntax.local_theory command_keywordsynthesize_notc "ML setup for synthetic definitions"
       (synth_constdecl >> (fn ((bndg,thm),p) => synthetic_def bndg thm p false false))

in

end
text‹The MLsynthetic_def function extracts definitions from
schematic goals. A new definition is added to the context. ›

(* example of use *)
(*
schematic_goal mem_formula_ex :
  assumes "m∈nat" "n∈ nat" "env ∈ list(M)"
  shows "nth(m,env) ∈ nth(n,env) ⟷ sats(M,?frm,env)"
  by (insert assms ; (rule sep_rules empty_iff_sats cartprod_iff_sats | simp del:sats_cartprod_fm)+)

synthesize "φ" from_schematic mem_formula_ex
*)

end

Theory Interface

section‹Interface between set models and Constructibility›

text‹This theory provides an interface between Paulson's
relativization results and set models of ZFC. In particular,
it is used to prove that the locale termforcing_data is
a sublocale of all relevant locales in ZF-Constructibility
(termM_trivial, termM_basic, termM_eclose, etc).›

theory Interface
  imports
    Nat_Miscellanea
    Relative_Univ
    Synthetic_Definition
begin

syntax
  "_sats"  :: "[i, i, i]  o"  ("(_, _  _)" [36,36,36] 60)
translations
  "(M,env  φ)"  "CONST sats(M,φ,env)"

abbreviation
  dec10  :: i   ("10") where "10  succ(9)"

abbreviation
  dec11  :: i   ("11") where "11  succ(10)"

abbreviation
  dec12  :: i   ("12") where "12  succ(11)"

abbreviation
  dec13  :: i   ("13") where "13  succ(12)"

abbreviation
  dec14  :: i   ("14") where "14  succ(13)"


definition
  infinity_ax :: "(i  o)  o" where
  "infinity_ax(M) 
      (I[M]. (z[M]. empty(M,z)  zI)  (y[M]. yI  (sy[M]. successor(M,y,sy)  syI)))"

definition
  choice_ax :: "(io)  o" where
  "choice_ax(M)  x[M]. a[M]. f[M]. ordinal(M,a)  surjection(M,a,x,f)"

context M_basic begin

lemma choice_ax_abs :
  "choice_ax(M)  (x[M]. a[M]. f[M]. Ord(a)  f  surj(a,x))"
  unfolding choice_ax_def
  by (simp)

end (* M_basic *)

definition
  wellfounded_trancl :: "[i=>o,i,i,i] => o" where
  "wellfounded_trancl(M,Z,r,p) 
      w[M]. wx[M]. rp[M].
               w  Z & pair(M,w,p,wx) & tran_closure(M,r,rp) & wx  rp"

lemma empty_intf :
  "infinity_ax(M) 
  (z[M]. empty(M,z))"
  by (auto simp add: empty_def infinity_ax_def)

lemma Transset_intf :
  "Transset(M)   yx  x  M  y  M"
  by (simp add: Transset_def,auto)

locale M_ZF_trans =
  fixes M
  assumes
    upair_ax:         "upair_ax(##M)"
    and Union_ax:         "Union_ax(##M)"
    and power_ax:         "power_ax(##M)"
    and extensionality:   "extensionality(##M)"
    and foundation_ax:    "foundation_ax(##M)"
    and infinity_ax:      "infinity_ax(##M)"
    and separation_ax:    "φformula  envlist(M)  arity(φ)  1 #+ length(env) 
                    separation(##M,λx. sats(M,φ,[x] @ env))"
    and replacement_ax:   "φformula  envlist(M)  arity(φ)  2 #+ length(env) 
                    strong_replacement(##M,λx y. sats(M,φ,[x,y] @ env))"
    and trans_M:          "Transset(M)"
begin


lemma TranssetI :
  "(y x. yx  xM  yM)  Transset(M)"
  by (auto simp add: Transset_def)

lemma zero_in_M:  "0  M"
proof -
  from infinity_ax have
    "(z[##M]. empty(##M,z))"
    by (rule empty_intf)
  then obtain z where
    zm: "empty(##M,z)"  "zM"
    by auto
  with trans_M have "z=0"
    by (simp  add: empty_def, blast intro: Transset_intf )
  with zm show ?thesis
    by simp
qed

subsection‹Interface with term‹M_trivial›
lemma mtrans :
  "M_trans(##M)"
  using Transset_intf[OF trans_M] zero_in_M exI[of "λx. xM"]
  by unfold_locales auto


lemma mtriv :
  "M_trivial(##M)"
  using trans_M M_trivial.intro mtrans M_trivial_axioms.intro upair_ax Union_ax
  by simp

end

sublocale M_ZF_trans  M_trivial "##M"
  by (rule mtriv)

context M_ZF_trans
begin

subsection‹Interface with term‹M_basic›

(* Inter_separation: "M(A) ⟹ separation(M, λx. ∀ y[M]. y∈A ⟹ x∈y)" *)
schematic_goal inter_fm_auto:
  assumes
    "nth(i,env) = x" "nth(j,env) = B"
    "i  nat" "j  nat" "env  list(A)"
  shows
    "(yA . yB  xy)  sats(A,?ifm(i,j),env)"
  by (insert assms ; (rule sep_rules | simp)+)

lemma inter_sep_intf :
  assumes
    "AM"
  shows
    "separation(##M,λx . yM . yA  xy)"
proof -
  obtain ifm where
    fmsats:"env. envlist(M)  ( yM. y(nth(1,env))  nth(0,env)y)
     sats(M,ifm(0,1),env)"
    and
    "ifm(0,1)  formula"
    and
    "arity(ifm(0,1)) = 2"
    using AM inter_fm_auto
    by (simp del:FOL_sats_iff add: nat_simp_union)
  then
  have "aM. separation(##M, λx. sats(M,ifm(0,1) , [x, a]))"
    using separation_ax by simp
  moreover
  have "(yM . ya  xy)  sats(M,ifm(0,1),[x,a])"
    if "aM" "xM" for a x
    using that fmsats[of "[x,a]"] by simp
  ultimately
  have "aM. separation(##M, λx . yM . ya  xy)"
    unfolding separation_def by simp
  with AM show ?thesis by simp
qed


(* Diff_separation: "M(B) ⟹ separation(M, λx. x ∉ B)" *)
schematic_goal diff_fm_auto:
  assumes
    "nth(i,env) = x" "nth(j,env) = B"
    "i  nat" "j  nat" "env  list(A)"
  shows
    "xB  sats(A,?dfm(i,j),env)"
  by (insert assms ; (rule sep_rules | simp)+)

lemma diff_sep_intf :
  assumes
    "BM"
  shows
    "separation(##M,λx . xB)"
proof -
  obtain dfm where
    fmsats:"env. envlist(M)  nth(0,env)nth(1,env)
     sats(M,dfm(0,1),env)"
    and
    "dfm(0,1)  formula"
    and
    "arity(dfm(0,1)) = 2"
    using BM diff_fm_auto
    by (simp del:FOL_sats_iff add: nat_simp_union)
  then
  have "bM. separation(##M, λx. sats(M,dfm(0,1) , [x, b]))"
    using separation_ax by simp
  moreover
  have "xb  sats(M,dfm(0,1),[x,b])"
    if "bM" "xM" for b x
    using that fmsats[of "[x,b]"] by simp
  ultimately
  have "bM. separation(##M, λx . xb)"
    unfolding separation_def by simp
  with BM show ?thesis by simp
qed

schematic_goal cprod_fm_auto:
  assumes
    "nth(i,env) = z" "nth(j,env) = B" "nth(h,env) = C"
    "i  nat" "j  nat" "h  nat" "env  list(A)"
  shows
    "(xA. xB  (yA. yC  pair(##A,x,y,z)))  sats(A,?cpfm(i,j,h),env)"
  by (insert assms ; (rule sep_rules | simp)+)


lemma cartprod_sep_intf :
  assumes
    "AM"
    and
    "BM"
  shows
    "separation(##M,λz. xM. xA  (yM. yB  pair(##M,x,y,z)))"
proof -
  obtain cpfm where
    fmsats:"env. envlist(M) 
    (xM. xnth(1,env)  (yM. ynth(2,env)  pair(##M,x,y,nth(0,env))))
     sats(M,cpfm(0,1,2),env)"
    and
    "cpfm(0,1,2)  formula"
    and
    "arity(cpfm(0,1,2)) = 3"
    using cprod_fm_auto by (simp del:FOL_sats_iff add: fm_defs nat_simp_union)
  then
  have "aM. bM. separation(##M, λz. sats(M,cpfm(0,1,2) , [z, a, b]))"
    using separation_ax by simp
  moreover
  have "(xM. xa  (yM. yb  pair(##M,x,y,z)))  sats(M,cpfm(0,1,2),[z,a,b])"
    if "aM" "bM" "zM" for a b z
    using that fmsats[of "[z,a,b]"] by simp
  ultimately
  have "aM. bM. separation(##M, λz . (xM. xa  (yM. yb  pair(##M,x,y,z))))"
    unfolding separation_def by simp
  with AM BM show ?thesis by simp
qed

schematic_goal im_fm_auto:
  assumes
    "nth(i,env) = y" "nth(j,env) = r" "nth(h,env) = B"
    "i  nat" "j  nat" "h  nat" "env  list(A)"
  shows
    "(pA. pr & (xA. xB & pair(##A,x,y,p)))  sats(A,?imfm(i,j,h),env)"
  by (insert assms ; (rule sep_rules | simp)+)

lemma image_sep_intf :
  assumes
    "AM"
    and
    "rM"
  shows
    "separation(##M, λy. pM. pr & (xM. xA & pair(##M,x,y,p)))"
proof -
  obtain imfm where
    fmsats:"env. envlist(M) 
    (pM. pnth(1,env) & (xM. xnth(2,env) & pair(##M,x,nth(0,env),p)))
     sats(M,imfm(0,1,2),env)"
    and
    "imfm(0,1,2)  formula"
    and
    "arity(imfm(0,1,2)) = 3"
    using im_fm_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "rM. aM. separation(##M, λy. sats(M,imfm(0,1,2) , [y,r,a]))"
    using separation_ax by simp
  moreover
  have "(pM. pk & (xM. xa & pair(##M,x,y,p)))  sats(M,imfm(0,1,2),[y,k,a])"
    if "kM" "aM" "yM" for k a y
    using that fmsats[of "[y,k,a]"] by simp
  ultimately
  have "kM. aM. separation(##M, λy . pM. pk & (xM. xa & pair(##M,x,y,p)))"
    unfolding separation_def by simp
  with rM AM show ?thesis by simp
qed

schematic_goal con_fm_auto:
  assumes
    "nth(i,env) = z" "nth(j,env) = R"
    "i  nat" "j  nat" "env  list(A)"
  shows
    "(pA. pR & (xA.yA. pair(##A,x,y,p) & pair(##A,y,x,z)))
   sats(A,?cfm(i,j),env)"
  by (insert assms ; (rule sep_rules | simp)+)


lemma converse_sep_intf :
  assumes
    "RM"
  shows
    "separation(##M,λz. pM. pR & (xM.yM. pair(##M,x,y,p) & pair(##M,y,x,z)))"
proof -
  obtain cfm where
    fmsats:"env. envlist(M) 
    (pM. pnth(1,env) & (xM.yM. pair(##M,x,y,p) & pair(##M,y,x,nth(0,env))))
     sats(M,cfm(0,1),env)"
    and
    "cfm(0,1)  formula"
    and
    "arity(cfm(0,1)) = 2"
    using con_fm_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "rM. separation(##M, λz. sats(M,cfm(0,1) , [z,r]))"
    using separation_ax by simp
  moreover
  have "(pM. pr & (xM.yM. pair(##M,x,y,p) & pair(##M,y,x,z))) 
          sats(M,cfm(0,1),[z,r])"
    if "zM" "rM" for z r
    using that fmsats[of "[z,r]"] by simp
  ultimately
  have "rM. separation(##M, λz . pM. pr & (xM.yM. pair(##M,x,y,p) & pair(##M,y,x,z)))"
    unfolding separation_def by simp
  with RM show ?thesis by simp
qed


schematic_goal rest_fm_auto:
  assumes
    "nth(i,env) = z" "nth(j,env) = C"
    "i  nat" "j  nat" "env  list(A)"
  shows
    "(xA. xC & (yA. pair(##A,x,y,z)))
   sats(A,?rfm(i,j),env)"
  by (insert assms ; (rule sep_rules | simp)+)


lemma restrict_sep_intf :
  assumes
    "AM"
  shows
    "separation(##M,λz. xM. xA & (yM. pair(##M,x,y,z)))"
proof -
  obtain rfm where
    fmsats:"env. envlist(M) 
    (xM. xnth(1,env) & (yM. pair(##M,x,y,nth(0,env))))
     sats(M,rfm(0,1),env)"
    and
    "rfm(0,1)  formula"
    and
    "arity(rfm(0,1)) = 2"
    using rest_fm_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "aM. separation(##M, λz. sats(M,rfm(0,1) , [z,a]))"
    using separation_ax by simp
  moreover
  have "(xM. xa & (yM. pair(##M,x,y,z))) 
          sats(M,rfm(0,1),[z,a])"
    if "zM" "aM" for z a
    using that fmsats[of "[z,a]"] by simp
  ultimately
  have "aM. separation(##M, λz . xM. xa & (yM. pair(##M,x,y,z)))"
    unfolding separation_def by simp
  with AM show ?thesis by simp
qed

schematic_goal comp_fm_auto:
  assumes
    "nth(i,env) = xz" "nth(j,env) = S" "nth(h,env) = R"
    "i  nat" "j  nat" "h  nat" "env  list(A)"
  shows
    "(xA. yA. zA. xyA. yzA.
              pair(##A,x,z,xz) & pair(##A,x,y,xy) & pair(##A,y,z,yz) & xyS & yzR)
   sats(A,?cfm(i,j,h),env)"
  by (insert assms ; (rule sep_rules | simp)+)


lemma comp_sep_intf :
  assumes
    "RM"
    and
    "SM"
  shows
    "separation(##M,λxz. xM. yM. zM. xyM. yzM.
              pair(##M,x,z,xz) & pair(##M,x,y,xy) & pair(##M,y,z,yz) & xyS & yzR)"
proof -
  obtain cfm where
    fmsats:"env. envlist(M) 
    (xM. yM. zM. xyM. yzM. pair(##M,x,z,nth(0,env)) &
            pair(##M,x,y,xy) & pair(##M,y,z,yz) & xynth(1,env) & yznth(2,env))
     sats(M,cfm(0,1,2),env)"
    and
    "cfm(0,1,2)  formula"
    and
    "arity(cfm(0,1,2)) = 3"
    using comp_fm_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "rM. sM. separation(##M, λy. sats(M,cfm(0,1,2) , [y,s,r]))"
    using separation_ax by simp
  moreover
  have "(xM. yM. zM. xyM. yzM.
              pair(##M,x,z,xz) & pair(##M,x,y,xy) & pair(##M,y,z,yz) & xys & yzr)
           sats(M,cfm(0,1,2) , [xz,s,r])"
    if "xzM" "sM" "rM" for xz s r
    using that fmsats[of "[xz,s,r]"] by simp
  ultimately
  have "sM. rM. separation(##M, λxz . xM. yM. zM. xyM. yzM.
              pair(##M,x,z,xz) & pair(##M,x,y,xy) & pair(##M,y,z,yz) & xys & yzr)"
    unfolding separation_def by simp
  with SM RM show ?thesis by simp
qed


schematic_goal pred_fm_auto:
  assumes
    "nth(i,env) = y" "nth(j,env) = R" "nth(h,env) = X"
    "i  nat" "j  nat" "h  nat" "env  list(A)"
  shows
    "(pA. pR & pair(##A,y,X,p))  sats(A,?pfm(i,j,h),env)"
  by (insert assms ; (rule sep_rules | simp)+)


lemma pred_sep_intf:
  assumes
    "RM"
    and
    "XM"
  shows
    "separation(##M, λy. pM. pR & pair(##M,y,X,p))"
proof -
  obtain pfm where
    fmsats:"env. envlist(M) 
    (pM. pnth(1,env) & pair(##M,nth(0,env),nth(2,env),p))  sats(M,pfm(0,1,2),env)"
    and
    "pfm(0,1,2)  formula"
    and
    "arity(pfm(0,1,2)) = 3"
    using pred_fm_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "xM. rM. separation(##M, λy. sats(M,pfm(0,1,2) , [y,r,x]))"
    using separation_ax by simp
  moreover
  have "(pM. pr & pair(##M,y,x,p))
           sats(M,pfm(0,1,2) , [y,r,x])"
    if "yM" "rM" "xM" for y x r
    using that fmsats[of "[y,r,x]"] by simp
  ultimately
  have "xM. rM. separation(##M, λ y . pM. pr & pair(##M,y,x,p))"
    unfolding separation_def by simp
  with XM RM show ?thesis by simp
qed

(* Memrel_separation:
     "separation(M, λz. ∃x[M]. ∃y[M]. pair(M,x,y,z) & x ∈ y)"
*)
schematic_goal mem_fm_auto:
  assumes
    "nth(i,env) = z" "i  nat" "env  list(A)"
  shows
    "(xA. yA. pair(##A,x,y,z) & x  y)  sats(A,?mfm(i),env)"
  by (insert assms ; (rule sep_rules | simp)+)

lemma memrel_sep_intf:
  "separation(##M, λz. xM. yM. pair(##M,x,y,z) & x  y)"
proof -
  obtain mfm where
    fmsats:"env. envlist(M) 
    (xM. yM. pair(##M,x,y,nth(0,env)) & x  y)  sats(M,mfm(0),env)"
    and
    "mfm(0)  formula"
    and
    "arity(mfm(0)) = 1"
    using mem_fm_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "separation(##M, λz. sats(M,mfm(0) , [z]))"
    using separation_ax by simp
  moreover
  have "(xM. yM. pair(##M,x,y,z) & x  y)  sats(M,mfm(0),[z])"
    if "zM" for z
    using that fmsats[of "[z]"] by simp
  ultimately
  have "separation(##M, λz . xM. yM. pair(##M,x,y,z) & x  y)"
    unfolding separation_def by simp
  then show ?thesis by simp
qed

schematic_goal recfun_fm_auto:
  assumes
    "nth(i1,env) = x" "nth(i2,env) = r" "nth(i3,env) = f" "nth(i4,env) = g" "nth(i5,env) = a"
    "nth(i6,env) = b" "i1nat" "i2nat" "i3nat" "i4nat" "i5nat" "i6nat" "env  list(A)"
  shows
    "(xaA. xbA. pair(##A,x,a,xa) & xa  r & pair(##A,x,b,xb) & xb  r &
                  (fxA. gxA. fun_apply(##A,f,x,fx) & fun_apply(##A,g,x,gx) & fx  gx))
     sats(A,?rffm(i1,i2,i3,i4,i5,i6),env)"
  by (insert assms ; (rule sep_rules | simp)+)


lemma is_recfun_sep_intf :
  assumes
    "rM" "fM" "gM" "aM" "bM"
  shows
    "separation(##M,λx. xaM. xbM.
                    pair(##M,x,a,xa) & xa  r & pair(##M,x,b,xb) & xb  r &
                    (fxM. gxM. fun_apply(##M,f,x,fx) & fun_apply(##M,g,x,gx) &
                                     fx  gx))"
proof -
  obtain rffm where
    fmsats:"env. envlist(M) 
    (xaM. xbM. pair(##M,nth(0,env),nth(4,env),xa) & xa  nth(1,env) &
    pair(##M,nth(0,env),nth(5,env),xb) & xb  nth(1,env) & (fxM. gxM.
    fun_apply(##M,nth(2,env),nth(0,env),fx) & fun_apply(##M,nth(3,env),nth(0,env),gx) & fx  gx))
     sats(M,rffm(0,1,2,3,4,5),env)"
    and
    "rffm(0,1,2,3,4,5)  formula"
    and
    "arity(rffm(0,1,2,3,4,5)) = 6"
    using recfun_fm_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "a1M. a2M. a3M. a4M. a5M.
        separation(##M, λx. sats(M,rffm(0,1,2,3,4,5) , [x,a1,a2,a3,a4,a5]))"
    using separation_ax by simp
  moreover
  have "(xaM. xbM. pair(##M,x,a4,xa) & xa  a1 & pair(##M,x,a5,xb) & xb  a1 &
          (fxM. gxM. fun_apply(##M,a2,x,fx) & fun_apply(##M,a3,x,gx) & fx  gx))
           sats(M,rffm(0,1,2,3,4,5) , [x,a1,a2,a3,a4,a5])"
    if "xM" "a1M" "a2M" "a3M" "a4M" "a5M"  for x a1 a2 a3 a4 a5
    using that fmsats[of "[x,a1,a2,a3,a4,a5]"] by simp
  ultimately
  have "a1M. a2M. a3M. a4M. a5M. separation(##M, λ x .
          xaM. xbM. pair(##M,x,a4,xa) & xa  a1 & pair(##M,x,a5,xb) & xb  a1 &
          (fxM. gxM. fun_apply(##M,a2,x,fx) & fun_apply(##M,a3,x,gx) & fx  gx))"
    unfolding separation_def by simp
  with rM fM gM aM bM show ?thesis by simp
qed


(* Instance of Replacement for M_basic *)

schematic_goal funsp_fm_auto:
  assumes
    "nth(i,env) = p" "nth(j,env) = z" "nth(h,env) = n"
    "i  nat" "j  nat" "h  nat" "env  list(A)"
  shows
    "(fA. bA. nbA. cnbfA. pair(##A,f,b,p) & pair(##A,n,b,nb) & is_cons(##A,nb,f,cnbf) &
    upair(##A,cnbf,cnbf,z))  sats(A,?fsfm(i,j,h),env)"
  by (insert assms ; (rule sep_rules | simp)+)


lemma funspace_succ_rep_intf :
  assumes
    "nM"
  shows
    "strong_replacement(##M,
          λp z. fM. bM. nbM. cnbfM.
                pair(##M,f,b,p) & pair(##M,n,b,nb) & is_cons(##M,nb,f,cnbf) &
                upair(##M,cnbf,cnbf,z))"
proof -
  obtain fsfm where
    fmsats:"envlist(M) 
    (fM. bM. nbM. cnbfM. pair(##M,f,b,nth(0,env)) & pair(##M,nth(2,env),b,nb)
      & is_cons(##M,nb,f,cnbf) & upair(##M,cnbf,cnbf,nth(1,env)))
     sats(M,fsfm(0,1,2),env)"
    and "fsfm(0,1,2)  formula" and "arity(fsfm(0,1,2)) = 3" for env
    using funsp_fm_auto[of concl:M] by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "n0M. strong_replacement(##M, λp z. sats(M,fsfm(0,1,2) , [p,z,n0]))"
    using replacement_ax by simp
  moreover
  have "(fM. bM. nbM. cnbfM. pair(##M,f,b,p) & pair(##M,n0,b,nb) &
          is_cons(##M,nb,f,cnbf) & upair(##M,cnbf,cnbf,z))
           sats(M,fsfm(0,1,2) , [p,z,n0])"
    if "pM" "zM" "n0M" for p z n0
    using that fmsats[of "[p,z,n0]"] by simp
  ultimately
  have "n0M. strong_replacement(##M, λ p z.
          fM. bM. nbM. cnbfM. pair(##M,f,b,p) & pair(##M,n0,b,nb) &
          is_cons(##M,nb,f,cnbf) & upair(##M,cnbf,cnbf,z))"
    unfolding strong_replacement_def univalent_def by simp
  with nM show ?thesis by simp
qed


(* Interface with M_basic *)

lemmas M_basic_sep_instances =
  inter_sep_intf diff_sep_intf cartprod_sep_intf
  image_sep_intf converse_sep_intf restrict_sep_intf
  pred_sep_intf memrel_sep_intf comp_sep_intf is_recfun_sep_intf

lemma mbasic : "M_basic(##M)"
  using trans_M zero_in_M power_ax M_basic_sep_instances funspace_succ_rep_intf mtriv
  by unfold_locales auto

end

sublocale M_ZF_trans  M_basic "##M"
  by (rule mbasic)

subsection‹Interface with term‹M_trancl›

(* rtran_closure_mem *)
schematic_goal rtran_closure_mem_auto:
  assumes
    "nth(i,env) = p" "nth(j,env) = r"  "nth(k,env) = B"
    "i  nat" "j  nat" "k  nat" "env  list(A)"
  shows
    "rtran_closure_mem(##A,B,r,p)  sats(A,?rcfm(i,j,k),env)"
  unfolding rtran_closure_mem_def
  by (insert assms ; (rule sep_rules | simp)+)


lemma (in M_ZF_trans) rtrancl_separation_intf:
  assumes
    "rM"
    and
    "AM"
  shows
    "separation (##M, rtran_closure_mem(##M,A,r))"
proof -
  obtain rcfm where
    fmsats:"env. envlist(M) 
    (rtran_closure_mem(##M,nth(2,env),nth(1,env),nth(0,env)))  sats(M,rcfm(0,1,2),env)"
    and
    "rcfm(0,1,2)  formula"
    and
    "arity(rcfm(0,1,2)) = 3"
    using rtran_closure_mem_auto by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "xM. aM. separation(##M, λy. sats(M,rcfm(0,1,2) , [y,x,a]))"
    using separation_ax by simp
  moreover
  have "(rtran_closure_mem(##M,a,x,y))
           sats(M,rcfm(0,1,2) , [y,x,a])"
    if "yM" "xM" "aM" for y x a
    using that fmsats[of "[y,x,a]"] by simp
  ultimately
  have "xM. aM. separation(##M, rtran_closure_mem(##M,a,x))"
    unfolding separation_def by simp
  with rM AM show ?thesis by simp
qed

schematic_goal rtran_closure_fm_auto:
  assumes
    "nth(i,env) = r" "nth(j,env) = rp"
    "i  nat" "j  nat" "env  list(A)"
  shows
    "rtran_closure(##A,r,rp)  sats(A,?rtc(i,j),env)"
  unfolding rtran_closure_def
  by (insert assms ; (rule sep_rules rtran_closure_mem_auto | simp)+)

schematic_goal trans_closure_fm_auto:
  assumes
    "nth(i,env) = r" "nth(j,env) = rp"
    "i  nat" "j  nat" "env  list(A)"
  shows
    "tran_closure(##A,r,rp)  sats(A,?tc(i,j),env)"
  unfolding tran_closure_def
  by (insert assms ; (rule sep_rules rtran_closure_fm_auto | simp))+

synthesize "trans_closure_fm" from_schematic trans_closure_fm_auto

schematic_goal wellfounded_trancl_fm_auto:
  assumes
    "nth(i,env) = p" "nth(j,env) = r"  "nth(k,env) = B"
    "i  nat" "j  nat" "k  nat" "env  list(A)"
  shows
    "wellfounded_trancl(##A,B,r,p)  sats(A,?wtf(i,j,k),env)"
  unfolding  wellfounded_trancl_def
  by (insert assms ; (rule sep_rules trans_closure_fm_iff_sats | simp)+)

lemma (in M_ZF_trans) wftrancl_separation_intf:
  assumes
    "rM"
    and
    "ZM"
  shows
    "separation (##M, wellfounded_trancl(##M,Z,r))"
proof -
  obtain rcfm where
    fmsats:"env. envlist(M) 
    (wellfounded_trancl(##M,nth(2,env),nth(1,env),nth(0,env)))  sats(M,rcfm(0,1,2),env)"
    and
    "rcfm(0,1,2)  formula"
    and
    "arity(rcfm(0,1,2)) = 3"
    using wellfounded_trancl_fm_auto[of concl:M "nth(2,_)"] unfolding fm_defs trans_closure_fm_def
    by (simp del:FOL_sats_iff pair_abs add: fm_defs nat_simp_union)
  then
  have "xM. zM. separation(##M, λy. sats(M,rcfm(0,1,2) , [y,x,z]))"
    using separation_ax by simp
  moreover
  have "(wellfounded_trancl(##M,z,x,y))
           sats(M,rcfm(0,1,2) , [y,x,z])"
    if "yM" "xM" "zM" for y x z
    using that fmsats[of "[y,x,z]"] by simp
  ultimately
  have "xM. zM. separation(##M, wellfounded_trancl(##M,z,x))"
    unfolding separation_def by simp
  with rM ZM show ?thesis by simp
qed

(* nat ∈ M *)

lemma (in M_ZF_trans) finite_sep_intf:
  "separation(##M, λx. xnat)"
proof -
  have "arity(finite_ordinal_fm(0)) = 1 "
    unfolding finite_ordinal_fm_def limit_ordinal_fm_def empty_fm_def succ_fm_def cons_fm_def
      union_fm_def upair_fm_def
    by (simp add: nat_union_abs1 Un_commute)
  with separation_ax
  have "(vM. separation(##M,λx. sats(M,finite_ordinal_fm(0),[x,v])))"
    by simp
  then have "(vM. separation(##M,finite_ordinal(##M)))"
    unfolding separation_def by simp
  then have "separation(##M,finite_ordinal(##M))"
    using zero_in_M by auto
  then show ?thesis unfolding separation_def by simp
qed


lemma (in M_ZF_trans) nat_subset_I' :
  " IM ; 0I ; x. xI  succ(x)I   nat  I"
  by (rule subsetI,induct_tac x,simp+)


lemma (in M_ZF_trans) nat_subset_I :
  "IM. nat  I"
proof -
  have "IM. 0I  (xM. xI  succ(x)I)"
    using infinity_ax unfolding infinity_ax_def by auto
  then obtain I where
    "IM" "0I" "(xM. xI  succ(x)I)"
    by auto
  then have "x. xI  succ(x)I"
    using Transset_intf[OF trans_M]  by simp
  then have "natI"
    using  IM 0I nat_subset_I' by simp
  then show ?thesis using IM by auto
qed

lemma (in M_ZF_trans) nat_in_M :
  "nat  M"
proof -
  have 1:"{xB . xA}=A" if "AB" for A B
    using that by auto
  obtain I where
    "IM" "natI"
    using nat_subset_I by auto
  then have "{xI . xnat}  M"
    using finite_sep_intf separation_closed[of "λx . xnat"] by simp
  then show ?thesis
    using ‹natI 1 by simp
qed
  (* end nat ∈ M *)


lemma (in M_ZF_trans) mtrancl : "M_trancl(##M)"
  using  mbasic rtrancl_separation_intf wftrancl_separation_intf nat_in_M
    wellfounded_trancl_def
  by unfold_locales auto

sublocale M_ZF_trans  M_trancl "##M"
  by (rule mtrancl)

subsection‹Interface with term‹M_eclose›

lemma repl_sats:
  assumes
    sat:"x z. xM  zM  sats(M,φ,Cons(x,Cons(z,env)))  P(x,z)"
  shows
    "strong_replacement(##M,λx z. sats(M,φ,Cons(x,Cons(z,env)))) 
   strong_replacement(##M,P)"
  by (rule strong_replacement_cong,simp add:sat)

lemma (in M_ZF_trans) nat_trans_M :
  "nM" if "nnat" for n
  using that nat_in_M Transset_intf[OF trans_M] by simp

lemma (in M_ZF_trans) list_repl1_intf:
  assumes
    "AM"
  shows
    "iterates_replacement(##M, is_list_functor(##M,A), 0)"
proof -
  {
    fix n
    assume "nnat"
    have "succ(n)M"
      using nnat› nat_trans_M by simp
    then have 1:"Memrel(succ(n))M"
      using nnat› Memrel_closed by simp
    have "0M"
      using  nat_0I nat_trans_M by simp
    then have "is_list_functor(##M, A, a, b)
        sats(M, list_functor_fm(13,1,0), [b,a,c,d,a0,a1,a2,a3,a4,y,x,z,Memrel(succ(n)),A,0])"
      if "aM" "bM" "cM" "dM" "a0M" "a1M" "a2M" "a3M" "a4M" "yM" "xM" "zM"
      for a b c d a0 a1 a2 a3 a4 y x z
      using that 1 AM list_functor_iff_sats by simp
    then have "sats(M, iterates_MH_fm(list_functor_fm(13,1,0),10,2,1,0), [a0,a1,a2,a3,a4,y,x,z,Memrel(succ(n)),A,0])
         iterates_MH(##M,is_list_functor(##M,A),0,a2, a1, a0)"
      if "a0M" "a1M" "a2M" "a3M" "a4M" "yM" "xM" "zM"
      for a0 a1 a2 a3 a4 y x z
      using that sats_iterates_MH_fm[of M "is_list_functor(##M,A)" _] 1 0M AM  by simp
    then have 2:"sats(M, is_wfrec_fm(iterates_MH_fm(list_functor_fm(13,1,0),10,2,1,0),3,1,0),
                            [y,x,z,Memrel(succ(n)),A,0])
        
        is_wfrec(##M, iterates_MH(##M,is_list_functor(##M,A),0) , Memrel(succ(n)), x, y)"
      if "yM" "xM" "zM" for y x z
      using  that sats_is_wfrec_fm 1 0M AM by simp
    let
      ?f="Exists(And(pair_fm(1,0,2),
               is_wfrec_fm(iterates_MH_fm(list_functor_fm(13,1,0),10,2,1,0),3,1,0)))"
    have satsf:"sats(M, ?f, [x,z,Memrel(succ(n)),A,0])
        
        (yM. pair(##M,x,y,z) &
        is_wfrec(##M, iterates_MH(##M,is_list_functor(##M,A),0) , Memrel(succ(n)), x, y))"
      if "xM" "zM" for x z
      using that 2 1 0M AM by (simp del:pair_abs)
    have "arity(?f) = 5"
      unfolding iterates_MH_fm_def is_wfrec_fm_def is_recfun_fm_def is_nat_case_fm_def
        restriction_fm_def list_functor_fm_def number1_fm_def cartprod_fm_def
        sum_fm_def quasinat_fm_def pre_image_fm_def fm_defs
      by (simp add:nat_simp_union)
    then
    have "strong_replacement(##M,λx z. sats(M,?f,[x,z,Memrel(succ(n)),A,0]))"
      using replacement_ax 1 AM 0M by simp
    then
    have "strong_replacement(##M,λx z.
          yM. pair(##M,x,y,z) & is_wfrec(##M, iterates_MH(##M,is_list_functor(##M,A),0) ,
                Memrel(succ(n)), x, y))"
      using repl_sats[of M ?f "[Memrel(succ(n)),A,0]"]  satsf by (simp del:pair_abs)
  }
  then
  show ?thesis unfolding iterates_replacement_def wfrec_replacement_def by simp
qed



(* Iterates_replacement para predicados sin parámetros *)
lemma (in M_ZF_trans) iterates_repl_intf :
  assumes
    "vM" and
    isfm:"is_F_fm  formula" and
    arty:"arity(is_F_fm)=2" and
    satsf: "a b env'.  aM ; bM ; env'list(M) 
               is_F(a,b)  sats(M, is_F_fm, [b,a]@env')"
  shows
    "iterates_replacement(##M,is_F,v)"
proof -
  {
    fix n
    assume "nnat"
    have "succ(n)M"
      using nnat› nat_trans_M by simp
    then have 1:"Memrel(succ(n))M"
      using nnat› Memrel_closed by simp
    {
      fix a0 a1 a2 a3 a4 y x z
      assume as:"a0M" "a1M" "a2M" "a3M" "a4M" "yM" "xM" "zM"
      have "sats(M, is_F_fm, Cons(b,Cons(a,Cons(c,Cons(d,[a0,a1,a2,a3,a4,y,x,z,Memrel(succ(n)),v])))))
           is_F(a,b)"
        if "aM" "bM" "cM" "dM" for a b c d
        using as that 1 satsf[of a b "[c,d,a0,a1,a2,a3,a4,y,x,z,Memrel(succ(n)),v]"] vM by simp
      then
      have "sats(M, iterates_MH_fm(is_F_fm,9,2,1,0), [a0,a1,a2,a3,a4,y,x,z,Memrel(succ(n)),v])
           iterates_MH(##M,is_F,v,a2, a1, a0)"
        using as
          sats_iterates_MH_fm[of M "is_F" "is_F_fm"] 1 vM by simp
    }
    then have 2:"sats(M, is_wfrec_fm(iterates_MH_fm(is_F_fm,9,2,1,0),3,1,0),
                            [y,x,z,Memrel(succ(n)),v])
        
        is_wfrec(##M, iterates_MH(##M,is_F,v),Memrel(succ(n)), x, y)"
      if "yM" "xM" "zM" for y x z
      using  that sats_is_wfrec_fm 1 vM by simp
    let
      ?f="Exists(And(pair_fm(1,0,2),
               is_wfrec_fm(iterates_MH_fm(is_F_fm,9,2,1,0),3,1,0)))"
    have satsf:"sats(M, ?f, [x,z,Memrel(succ(n)),v])
        
        (yM. pair(##M,x,y,z) &
        is_wfrec(##M, iterates_MH(##M,is_F,v) , Memrel(succ(n)), x, y))"
      if "xM" "zM" for x z
      using that 2 1 vM by (simp del:pair_abs)
    have "arity(?f) = 4"
      unfolding iterates_MH_fm_def is_wfrec_fm_def is_recfun_fm_def is_nat_case_fm_def
        restriction_fm_def pre_image_fm_def quasinat_fm_def fm_defs
      using arty by (simp add:nat_simp_union)
    then
    have "strong_replacement(##M,λx z. sats(M,?f,[x,z,Memrel(succ(n)),v]))"
      using replacement_ax 1 vM is_F_fmformula› by simp
    then
    have "strong_replacement(##M,λx z.
          yM. pair(##M,x,y,z) & is_wfrec(##M, iterates_MH(##M,is_F,v) ,
                Memrel(succ(n)), x, y))"
      using repl_sats[of M ?f "[Memrel(succ(n)),v]"]  satsf by (simp del:pair_abs)
  }
  then
  show ?thesis unfolding iterates_replacement_def wfrec_replacement_def by simp
qed

lemma (in M_ZF_trans) formula_repl1_intf :
  "iterates_replacement(##M, is_formula_functor(##M), 0)"
proof -
  have "0M"
    using  nat_0I nat_trans_M by simp
  have 1:"arity(formula_functor_fm(1,0)) = 2"
    unfolding formula_functor_fm_def fm_defs sum_fm_def cartprod_fm_def number1_fm_def
    by (simp add:nat_simp_union)
  have 2:"formula_functor_fm(1,0)formula" by simp
  have "is_formula_functor(##M,a,b) 
        sats(M, formula_functor_fm(1,0), [b,a])"
    if "aM" "bM"  for a b
    using that by simp
  then show ?thesis using 0M 1 2 iterates_repl_intf by simp
qed

lemma (in M_ZF_trans) nth_repl_intf:
  assumes
    "l  M"
  shows
    "iterates_replacement(##M,λl' t. is_tl(##M,l',t),l)"
proof -
  have 1:"arity(tl_fm(1,0)) = 2"
    unfolding tl_fm_def fm_defs quasilist_fm_def Cons_fm_def Nil_fm_def Inr_fm_def number1_fm_def
      Inl_fm_def by (simp add:nat_simp_union)
  have 2:"tl_fm(1,0)formula" by simp
  have "is_tl(##M,a,b)  sats(M, tl_fm(1,0), [b,a])"
    if "aM" "bM" for a b
    using that by simp
  then show ?thesis using lM 1 2 iterates_repl_intf by simp
qed


lemma (in M_ZF_trans) eclose_repl1_intf:
  assumes
    "AM"
  shows
    "iterates_replacement(##M, big_union(##M), A)"
proof -
  have 1:"arity(big_union_fm(1,0)) = 2"
    unfolding big_union_fm_def fm_defs by (simp add:nat_simp_union)
  have 2:"big_union_fm(1,0)formula" by simp
  have "big_union(##M,a,b)  sats(M, big_union_fm(1,0), [b,a])"
    if "aM" "bM" for a b
    using that by simp
  then show ?thesis using AM 1 2 iterates_repl_intf by simp
qed

(*
    and list_replacement2:
   "M(A) ⟹ strong_replacement(M,
         λn y. n∈nat & is_iterates(M, is_list_functor(M,A), 0, n, y))"

*)
lemma (in M_ZF_trans) list_repl2_intf:
  assumes
    "AM"
  shows
    "strong_replacement(##M,λn y. nnat & is_iterates(##M, is_list_functor(##M,A), 0, n, y))"
proof -
  have "0M"
    using  nat_0I nat_trans_M by simp
  have "is_list_functor(##M,A,a,b) 
        sats(M,list_functor_fm(13,1,0),[b,a,c,d,e,f,g,h,i,j,k,n,y,A,0,nat])"
    if "aM" "bM" "cM" "dM" "eM" "fM""gM""hM""iM""jM" "kM" "nM" "yM"
    for a b c d e f g h i j k n y
    using that 0M nat_in_M AM by simp
  then
  have 1:"sats(M, is_iterates_fm(list_functor_fm(13,1,0),3,0,1),[n,y,A,0,nat] ) 
           is_iterates(##M, is_list_functor(##M,A), 0, n , y)"
    if "nM" "yM" for n y
    using that 0M AM nat_in_M
      sats_is_iterates_fm[of M "is_list_functor(##M,A)"] by simp
  let ?f = "And(Member(0,4),is_iterates_fm(list_functor_fm(13,1,0),3,0,1))"
  have satsf:"sats(M, ?f,[n,y,A,0,nat] ) 
        nnat & is_iterates(##M, is_list_functor(##M,A), 0, n, y)"
    if "nM" "yM" for n y
    using that 0M AM nat_in_M 1 by simp
  have "arity(?f) = 5"
    unfolding is_iterates_fm_def restriction_fm_def list_functor_fm_def number1_fm_def Memrel_fm_def
      cartprod_fm_def sum_fm_def quasinat_fm_def pre_image_fm_def fm_defs is_wfrec_fm_def
      is_recfun_fm_def iterates_MH_fm_def is_nat_case_fm_def
    by (simp add:nat_simp_union)
  then
  have "strong_replacement(##M,λn y. sats(M,?f,[n,y,A,0,nat]))"
    using replacement_ax 1 nat_in_M AM 0M by simp
  then
  show ?thesis using repl_sats[of M ?f "[A,0,nat]"]  satsf  by simp
qed

lemma (in M_ZF_trans) formula_repl2_intf:
  "strong_replacement(##M,λn y. nnat & is_iterates(##M, is_formula_functor(##M), 0, n, y))"
proof -
  have "0M"
    using  nat_0I nat_trans_M by simp
  have "is_formula_functor(##M,a,b) 
        sats(M,formula_functor_fm(1,0),[b,a,c,d,e,f,g,h,i,j,k,n,y,0,nat])"
    if "aM" "bM" "cM" "dM" "eM" "fM""gM""hM""iM""jM" "kM" "nM" "yM"
    for a b c d e f g h i j k n y
    using that 0M nat_in_M by simp
  then
  have 1:"sats(M, is_iterates_fm(formula_functor_fm(1,0),2,0,1),[n,y,0,nat] ) 
           is_iterates(##M, is_formula_functor(##M), 0, n , y)"
    if "nM" "yM" for n y
    using that 0M nat_in_M
      sats_is_iterates_fm[of M "is_formula_functor(##M)"] by simp
  let ?f = "And(Member(0,3),is_iterates_fm(formula_functor_fm(1,0),2,0,1))"
  have satsf:"sats(M, ?f,[n,y,0,nat] ) 
        nnat & is_iterates(##M, is_formula_functor(##M), 0, n, y)"
    if "nM" "yM" for n y
    using that 0M nat_in_M 1 by simp
  have artyf:"arity(?f) = 4"
    unfolding is_iterates_fm_def formula_functor_fm_def fm_defs sum_fm_def quasinat_fm_def
      cartprod_fm_def number1_fm_def Memrel_fm_def ordinal_fm_def transset_fm_def
      is_wfrec_fm_def is_recfun_fm_def iterates_MH_fm_def is_nat_case_fm_def subset_fm_def
      pre_image_fm_def restriction_fm_def
    by (simp add:nat_simp_union)
  then
  have "strong_replacement(##M,λn y. sats(M,?f,[n,y,0,nat]))"
    using replacement_ax 1 artyf 0M nat_in_M by simp
  then
  show ?thesis using repl_sats[of M ?f "[0,nat]"]  satsf  by simp
qed


(*
   "M(A) ⟹ strong_replacement(M,
         λn y. n∈nat & is_iterates(M, big_union(M), A, n, y))"
*)

lemma (in M_ZF_trans) eclose_repl2_intf:
  assumes
    "AM"
  shows
    "strong_replacement(##M,λn y. nnat & is_iterates(##M, big_union(##M), A, n, y))"
proof -
  have "big_union(##M,a,b) 
        sats(M,big_union_fm(1,0),[b,a,c,d,e,f,g,h,i,j,k,n,y,A,nat])"
    if "aM" "bM" "cM" "dM" "eM" "fM""gM""hM""iM""jM" "kM" "nM" "yM"
    for a b c d e f g h i j k n y
    using that AM nat_in_M by simp
  then
  have 1:"sats(M, is_iterates_fm(big_union_fm(1,0),2,0,1),[n,y,A,nat] ) 
           is_iterates(##M, big_union(##M), A, n , y)"
    if "nM" "yM" for n y
    using that AM nat_in_M
      sats_is_iterates_fm[of M "big_union(##M)"] by simp
  let ?f = "And(Member(0,3),is_iterates_fm(big_union_fm(1,0),2,0,1))"
  have satsf:"sats(M, ?f,[n,y,A,nat] ) 
        nnat & is_iterates(##M, big_union(##M), A, n, y)"
    if "nM" "yM" for n y
    using that AM nat_in_M 1 by simp
  have artyf:"arity(?f) = 4"
    unfolding is_iterates_fm_def formula_functor_fm_def fm_defs sum_fm_def quasinat_fm_def
      cartprod_fm_def number1_fm_def Memrel_fm_def ordinal_fm_def transset_fm_def
      is_wfrec_fm_def is_recfun_fm_def iterates_MH_fm_def is_nat_case_fm_def subset_fm_def
      pre_image_fm_def restriction_fm_def
    by (simp add:nat_simp_union)
  then
  have "strong_replacement(##M,λn y. sats(M,?f,[n,y,A,nat]))"
    using replacement_ax 1 artyf AM nat_in_M by simp
  then
  show ?thesis using repl_sats[of M ?f "[A,nat]"]  satsf  by simp
qed

lemma (in M_ZF_trans) mdatatypes : "M_datatypes(##M)"
  using  mtrancl list_repl1_intf list_repl2_intf formula_repl1_intf
    formula_repl2_intf nth_repl_intf
  by unfold_locales auto

sublocale M_ZF_trans  M_datatypes "##M"
  by (rule mdatatypes)

lemma (in M_ZF_trans) meclose : "M_eclose(##M)"
  using mdatatypes eclose_repl1_intf eclose_repl2_intf
  by unfold_locales auto

sublocale M_ZF_trans  M_eclose "##M"
  by (rule meclose)

(* Interface with locale M_eclose_pow *)

(* "powerset(M,A,z) ≡ ∀x[M]. x ∈ z ⟷ subset(M,x,A)" *)
definition
  powerset_fm :: "[i,i]  i" where
  "powerset_fm(A,z)  Forall(Iff(Member(0,succ(z)),subset_fm(0,succ(A))))"

lemma powerset_type [TC]:
  " x  nat; y  nat   powerset_fm(x,y)  formula"
  by (simp add:powerset_fm_def)

definition
  is_powapply_fm :: "[i,i,i]  i" where
  "is_powapply_fm(f,y,z) 
      Exists(And(fun_apply_fm(succ(f), succ(y), 0),
            Forall(Iff(Member(0, succ(succ(z))),
            Forall(Implies(Member(0, 1), Member(0, 2)))))))"

lemma is_powapply_type [TC] :
  "fnat ; ynat; znat  is_powapply_fm(f,y,z)formula"
  unfolding is_powapply_fm_def by simp

lemma sats_is_powapply_fm :
  assumes
    "fnat" "ynat" "znat" "envlist(A)" "0A"
  shows
    "is_powapply(##A,nth(f, env),nth(y, env),nth(z, env))
     sats(A,is_powapply_fm(f,y,z),env)"
  unfolding is_powapply_def is_powapply_fm_def is_Collect_def powerset_def subset_def
  using nth_closed assms by simp


lemma (in M_ZF_trans) powapply_repl :
  assumes
    "fM"
  shows
    "strong_replacement(##M,is_powapply(##M,f))"
proof -
  have "arity(is_powapply_fm(2,0,1)) = 3"
    unfolding is_powapply_fm_def
    by (simp add: fm_defs nat_simp_union)
  then
  have "f0M. strong_replacement(##M, λp z. sats(M,is_powapply_fm(2,0,1) , [p,z,f0]))"
    using replacement_ax by simp
  moreover
  have "is_powapply(##M,f0,p,z)  sats(M,is_powapply_fm(2,0,1) , [p,z,f0])"
    if "pM" "zM" "f0M" for p z f0
    using that zero_in_M sats_is_powapply_fm[of 2 0 1 "[p,z,f0]" M] by simp
  ultimately
  have "f0M. strong_replacement(##M, is_powapply(##M,f0))"
    unfolding strong_replacement_def univalent_def by simp
  with fM show ?thesis by simp
qed


(*"PHrank(M,f,y,z) ≡ M(z) ∧ (∃fy[M]. fun_apply(M,f,y,fy) ∧ successor(M,fy,z))"*)
definition
  PHrank_fm :: "[i,i,i]  i" where
  "PHrank_fm(f,y,z)  Exists(And(fun_apply_fm(succ(f),succ(y),0)
                                 ,succ_fm(0,succ(z))))"

lemma PHrank_type [TC]:
  " x  nat; y  nat; z  nat   PHrank_fm(x,y,z)  formula"
  by (simp add:PHrank_fm_def)


lemma (in M_ZF_trans) sats_PHrank_fm [simp]:
  " x  nat; y  nat; z  nat;  env  list(M)  
     sats(M,PHrank_fm(x,y,z),env) 
        PHrank(##M,nth(x,env),nth(y,env),nth(z,env))"
  using zero_in_M Internalizations.nth_closed by (simp add: PHrank_def PHrank_fm_def)


lemma (in M_ZF_trans) phrank_repl :
  assumes
    "fM"
  shows
    "strong_replacement(##M,PHrank(##M,f))"
proof -
  have "arity(PHrank_fm(2,0,1)) = 3"
    unfolding PHrank_fm_def
    by (simp add: fm_defs nat_simp_union)
  then
  have "f0M. strong_replacement(##M, λp z. sats(M,PHrank_fm(2,0,1) , [p,z,f0]))"
    using replacement_ax by simp
  then
  have "f0M. strong_replacement(##M, PHrank(##M,f0))"
    unfolding strong_replacement_def univalent_def by simp
  with fM show ?thesis by simp
qed


(*"is_Hrank(M,x,f,hc) ≡ (∃R[M]. big_union(M,R,hc) ∧is_Replace(M,x,PHrank(M,f),R)) "*)
definition
  is_Hrank_fm :: "[i,i,i]  i" where
  "is_Hrank_fm(x,f,hc)  Exists(And(big_union_fm(0,succ(hc)),
                                Replace_fm(succ(x),PHrank_fm(succ(succ(succ(f))),0,1),0)))"

lemma is_Hrank_type [TC]:
  " x  nat; y  nat; z  nat   is_Hrank_fm(x,y,z)  formula"
  by (simp add:is_Hrank_fm_def)

lemma (in M_ZF_trans) sats_is_Hrank_fm [simp]:
  " x  nat; y  nat; z  nat; env  list(M)
     sats(M,is_Hrank_fm(x,y,z),env) 
        is_Hrank(##M,nth(x,env),nth(y,env),nth(z,env))"
  using zero_in_M is_Hrank_def is_Hrank_fm_def sats_Replace_fm
  by simp

(* M(x) ⟹ wfrec_replacement(M,is_Hrank(M),rrank(x)) *)
lemma (in M_ZF_trans) wfrec_rank :
  assumes
    "XM"
  shows
    "wfrec_replacement(##M,is_Hrank(##M),rrank(X))"
proof -
  have
    "is_Hrank(##M,a2, a1, a0) 
             sats(M, is_Hrank_fm(2,1,0), [a0,a1,a2,a3,a4,y,x,z,rrank(X)])"
    if "a4M" "a3M" "a2M" "a1M" "a0M" "yM" "xM" "zM" for a4 a3 a2 a1 a0 y x z
    using that rrank_in_M XM by simp
  then
  have
    1:"sats(M, is_wfrec_fm(is_Hrank_fm(2,1,0),3,1,0),[y,x,z,rrank(X)])
   is_wfrec(##M, is_Hrank(##M) ,rrank(X), x, y)"
    if "yM" "xM" "zM" for y x z
    using that XM rrank_in_M sats_is_wfrec_fm by simp
  let
    ?f="Exists(And(pair_fm(1,0,2),is_wfrec_fm(is_Hrank_fm(2,1,0),3,1,0)))"
  have satsf:"sats(M, ?f, [x,z,rrank(X)])
               (yM. pair(##M,x,y,z) & is_wfrec(##M, is_Hrank(##M) , rrank(X), x, y))"
    if "xM" "zM" for x z
    using that 1 XM rrank_in_M by (simp del:pair_abs)
  have "arity(?f) = 3"
    unfolding is_wfrec_fm_def is_recfun_fm_def is_nat_case_fm_def is_Hrank_fm_def PHrank_fm_def
      restriction_fm_def list_functor_fm_def number1_fm_def cartprod_fm_def
      sum_fm_def quasinat_fm_def pre_image_fm_def fm_defs
    by (simp add:nat_simp_union)
  then
  have "strong_replacement(##M,λx z. sats(M,?f,[x,z,rrank(X)]))"
    using replacement_ax 1 XM rrank_in_M by simp
  then
  have "strong_replacement(##M,λx z.
          yM. pair(##M,x,y,z) & is_wfrec(##M, is_Hrank(##M) , rrank(X), x, y))"
    using repl_sats[of M ?f "[rrank(X)]"]  satsf by (simp del:pair_abs)
  then
  show ?thesis unfolding wfrec_replacement_def  by simp
qed

(*"is_HVfrom(M,A,x,f,h) ≡ ∃U[M]. ∃R[M].  union(M,A,U,h)
        ∧ big_union(M,R,U) ∧ is_Replace(M,x,is_powapply(M,f),R)"*)
definition
  is_HVfrom_fm :: "[i,i,i,i]  i" where
  "is_HVfrom_fm(A,x,f,h)  Exists(Exists(And(union_fm(A #+ 2,1,h #+ 2),
                            And(big_union_fm(0,1),
                            Replace_fm(x #+ 2,is_powapply_fm(f #+ 4,0,1),0)))))"

lemma is_HVfrom_type [TC]:
  " Anat; x  nat; f  nat; h  nat   is_HVfrom_fm(A,x,f,h)  formula"
  by (simp add:is_HVfrom_fm_def)

lemma sats_is_HVfrom_fm :
  " anat; x  nat; f  nat; h  nat; env  list(A); 0A
     sats(A,is_HVfrom_fm(a,x,f,h),env) 
        is_HVfrom(##A,nth(a,env),nth(x,env),nth(f,env),nth(h,env))"
  using is_HVfrom_def is_HVfrom_fm_def sats_Replace_fm[OF sats_is_powapply_fm]
  by simp

lemma is_HVfrom_iff_sats:
  assumes
    "nth(a,env) = aa" "nth(x,env) = xx" "nth(f,env) = ff" "nth(h,env) = hh"
    "anat" "xnat" "fnat" "hnat" "envlist(A)" "0A"
  shows
    "is_HVfrom(##A,aa,xx,ff,hh)  sats(A, is_HVfrom_fm(a,x,f,h), env)"
  using assms sats_is_HVfrom_fm by simp

(* FIX US *)
schematic_goal sats_is_Vset_fm_auto:
  assumes
    "inat" "vnat" "envlist(A)" "0A"
    "i < length(env)" "v < length(env)"
  shows
    "is_Vset(##A,nth(i, env),nth(v, env))
     sats(A,?ivs_fm(i,v),env)"
  unfolding is_Vset_def is_Vfrom_def
  by (insert assms; (rule sep_rules is_HVfrom_iff_sats is_transrec_iff_sats | simp)+)

schematic_goal is_Vset_iff_sats:
  assumes
    "nth(i,env) = ii" "nth(v,env) = vv"
    "inat" "vnat" "envlist(A)" "0A"
    "i < length(env)" "v < length(env)"
  shows
    "is_Vset(##A,ii,vv)  sats(A, ?ivs_fm(i,v), env)"
  unfolding ‹nth(i,env) = ii[symmetric] ‹nth(v,env) = vv[symmetric]
  by (rule sats_is_Vset_fm_auto(1); simp add:assms)


lemma (in M_ZF_trans) memrel_eclose_sing :
  "aM  saM. esaM. mesaM.
       upair(##M,a,a,sa) & is_eclose(##M,sa,esa) & membership(##M,esa,mesa)"
  using upair_ax eclose_closed Memrel_closed unfolding upair_ax_def
  by (simp del:upair_abs)


lemma (in M_ZF_trans) trans_repl_HVFrom :
  assumes
    "AM" "iM"
  shows
    "transrec_replacement(##M,is_HVfrom(##M,A),i)"
proof -
  { fix mesa
    assume "mesaM"
    have
      0:"is_HVfrom(##M,A,a2, a1, a0) 
      sats(M, is_HVfrom_fm(8,2,1,0), [a0,a1,a2,a3,a4,y,x,z,A,mesa])"
      if "a4M" "a3M" "a2M" "a1M" "a0M" "yM" "xM" "zM" for a4 a3 a2 a1 a0 y x z
      using that zero_in_M sats_is_HVfrom_fm mesaM AM by simp
    have
      1:"sats(M, is_wfrec_fm(is_HVfrom_fm(8,2,1,0),4,1,0),[y,x,z,A,mesa])
         is_wfrec(##M, is_HVfrom(##M,A),mesa, x, y)"
      if "yM" "xM" "zM" for y x z
      using that AM mesaM sats_is_wfrec_fm[OF 0] by simp
    let
      ?f="Exists(And(pair_fm(1,0,2),is_wfrec_fm(is_HVfrom_fm(8,2,1,0),4,1,0)))"
    have satsf:"sats(M, ?f, [x,z,A,mesa])
               (yM. pair(##M,x,y,z) & is_wfrec(##M, is_HVfrom(##M,A) , mesa, x, y))"
      if "xM" "zM" for x z
      using that 1 AM mesaM by (simp del:pair_abs)
    have "arity(?f) = 4"
      unfolding is_HVfrom_fm_def is_wfrec_fm_def is_recfun_fm_def is_nat_case_fm_def
        restriction_fm_def list_functor_fm_def number1_fm_def cartprod_fm_def
        is_powapply_fm_def sum_fm_def quasinat_fm_def pre_image_fm_def fm_defs
      by (simp add:nat_simp_union)
    then
    have "strong_replacement(##M,λx z. sats(M,?f,[x,z,A,mesa]))"
      using replacement_ax 1 AM mesaM by simp
    then
    have "strong_replacement(##M,λx z.
          yM. pair(##M,x,y,z) & is_wfrec(##M, is_HVfrom(##M,A) , mesa, x, y))"
      using repl_sats[of M ?f "[A,mesa]"]  satsf by (simp del:pair_abs)
    then
    have "wfrec_replacement(##M,is_HVfrom(##M,A),mesa)"
      unfolding wfrec_replacement_def  by simp
  }
  then show ?thesis unfolding transrec_replacement_def
    using iM memrel_eclose_sing by simp
qed


lemma (in M_ZF_trans) meclose_pow : "M_eclose_pow(##M)"
  using meclose power_ax powapply_repl phrank_repl trans_repl_HVFrom wfrec_rank
  by unfold_locales auto

sublocale M_ZF_trans  M_eclose_pow "##M"
  by (rule meclose_pow)

lemma (in M_ZF_trans) repl_gen :
  assumes
    f_abs: "x y.  xM; yM   is_F(##M,x,y)  y = f(x)"
    and
    f_sats: "x y. xM ; yM  
             sats(M,f_fm,Cons(x,Cons(y,env)))  is_F(##M,x,y)"
    and
    f_form: "f_fm  formula"
    and
    f_arty: "arity(f_fm) = 2"
    and
    "envlist(M)"
  shows
    "strong_replacement(##M, λx y. y = f(x))"
proof -
  have "sats(M,f_fm,[x,y]@env)  is_F(##M,x,y)" if "xM" "yM" for x y
    using that f_sats[of x y] by simp
  moreover
  from f_form f_arty
  have "strong_replacement(##M, λx y. sats(M,f_fm,[x,y]@env))"
    using envlist(M) replacement_ax by simp
  ultimately
  have "strong_replacement(##M, is_F(##M))"
    using strong_replacement_cong[of "##M" "λx y. sats(M,f_fm,[x,y]@env)" "is_F(##M)"] by simp
  with f_abs show ?thesis
    using strong_replacement_cong[of "##M" "is_F(##M)" "λx y. y = f(x)"] by simp
qed

(* Proof Scheme for instances of separation *)
lemma (in M_ZF_trans) sep_in_M :
  assumes
    "φ  formula" "envlist(M)"
    "arity(φ)  1 #+ length(env)" "AM" and
    satsQ: "x. xM  sats(M,φ,[x]@env)  Q(x)"
  shows
    "{yA . Q(y)}M"
proof -
  have "separation(##M,λx. sats(M,φ,[x] @ env))"
    using assms separation_ax by simp
  then show ?thesis using
      AM satsQ trans_M
      separation_cong[of "##M" "λy. sats(M,φ,[y]@env)" "Q"]
      separation_closed  by simp
qed

end

Theory Forcing_Data

section‹Transitive set models of ZF›
text‹This theory defines the locale termM_ZF_trans for
transitive models of ZF, and the associated termforcing_data
 that adds a forcing notion›
theory Forcing_Data
  imports  
    Forcing_Notions 
    Interface

begin

lemma Transset_M :
  "Transset(M)   yx  x  M  y  M"
  by (simp add: Transset_def,auto)  


locale M_ZF = 
  fixes M 
  assumes 
    upair_ax:         "upair_ax(##M)"
    and Union_ax:         "Union_ax(##M)"
    and power_ax:         "power_ax(##M)"
    and extensionality:   "extensionality(##M)"
    and foundation_ax:    "foundation_ax(##M)"
    and infinity_ax:      "infinity_ax(##M)"
    and separation_ax:    "φformula  envlist(M)  arity(φ)  1 #+ length(env) 
                    separation(##M,λx. sats(M,φ,[x] @ env))" 
    and replacement_ax:   "φformula  envlist(M)  arity(φ)  2 #+ length(env)  
                    strong_replacement(##M,λx y. sats(M,φ,[x,y] @ env))" 

locale M_ctm = M_ZF +
  fixes enum
  assumes M_countable:      "enumbij(nat,M)"
    and trans_M:          "Transset(M)"

begin
interpretation intf: M_ZF_trans "M"
  using M_ZF_trans.intro
    trans_M upair_ax Union_ax power_ax extensionality
    foundation_ax infinity_ax separation_ax[simplified] 
    replacement_ax[simplified]
  by simp


lemmas transitivity = Transset_intf[OF trans_M]

lemma zero_in_M:  "0  M" 
  by (rule intf.zero_in_M)

lemma tuples_in_M: "AM  BM  A,BM" 
  by (simp flip:setclass_iff)

lemma nat_in_M : "nat  M"
  by (rule intf.nat_in_M)

lemma n_in_M : "nnat  nM"
  using nat_in_M transitivity by simp

lemma mtriv: "M_trivial(##M)" 
  by (rule intf.mtriv)

lemma mtrans: "M_trans(##M)"
  by (rule intf.mtrans)

lemma mbasic: "M_basic(##M)"
  by (rule intf.mbasic)

lemma mtrancl: "M_trancl(##M)"
  by (rule intf.mtrancl)

lemma mdatatypes: "M_datatypes(##M)"
  by (rule intf.mdatatypes)

lemma meclose: "M_eclose(##M)"
  by (rule intf.meclose)

lemma meclose_pow: "M_eclose_pow(##M)"
  by (rule intf.meclose_pow)



end (* M_ctm *)

(* M_ctm interface *)
sublocale M_ctm  M_trivial "##M"
  by  (rule mtriv)

sublocale M_ctm  M_trans "##M"
  by  (rule mtrans)

sublocale M_ctm  M_basic "##M"
  by  (rule mbasic)

sublocale M_ctm  M_trancl "##M"
  by  (rule mtrancl)

sublocale M_ctm  M_datatypes "##M"
  by  (rule mdatatypes)

sublocale M_ctm  M_eclose "##M"
  by  (rule meclose)

sublocale M_ctm  M_eclose_pow "##M"
  by  (rule meclose_pow)

(* end interface *)

context M_ctm
begin

subsectiontermCollects in $M$›
lemma Collect_in_M_0p :
  assumes
    Qfm : "Q_fm  formula" and
    Qarty : "arity(Q_fm) = 1" and
    Qsats : "x. xM  sats(M,Q_fm,[x])  is_Q(##M,x)" and
    Qabs  : "x. xM  is_Q(##M,x)  Q(x)" and
    "AM"
  shows
    "Collect(A,Q)M" 
proof -
  have "zA  zM" for z
    using AM transitivity[of z A] by simp
  then
  have 1:"Collect(A,is_Q(##M)) = Collect(A,Q)" 
    using Qabs Collect_cong[of "A" "A" "is_Q(##M)" "Q"] by simp
  have "separation(##M,is_Q(##M))"
    using separation_ax Qsats Qarty Qfm
      separation_cong[of "##M" "λy. sats(M,Q_fm,[y])" "is_Q(##M)"]
    by simp
  then 
  have "Collect(A,is_Q(##M))M"
    using separation_closed AM by simp 
  then
  show ?thesis using 1 by simp
qed

lemma Collect_in_M_2p :
  assumes
    Qfm : "Q_fm  formula" and
    Qarty : "arity(Q_fm) = 3" and
    params_M : "yM" "zM" and
    Qsats : "x. xM  sats(M,Q_fm,[x,y,z])  is_Q(##M,x,y,z)" and
    Qabs  : "x. xM  is_Q(##M,x,y,z)  Q(x,y,z)" and
    "AM"
  shows
    "Collect(A,λx. Q(x,y,z))M" 
proof -
  have "zA  zM" for z
    using AM transitivity[of z A] by simp
  then
  have 1:"Collect(A,λx. is_Q(##M,x,y,z)) = Collect(A,λx. Q(x,y,z))" 
    using Qabs Collect_cong[of "A" "A" "λx. is_Q(##M,x,y,z)" "λx. Q(x,y,z)"] by simp
  have "separation(##M,λx. is_Q(##M,x,y,z))"
    using separation_ax Qsats Qarty Qfm params_M
      separation_cong[of "##M" "λx. sats(M,Q_fm,[x,y,z])" "λx. is_Q(##M,x,y,z)"]
    by simp
  then 
  have "Collect(A,λx. is_Q(##M,x,y,z))M"
    using separation_closed AM by simp 
  then
  show ?thesis using 1 by simp
qed

lemma Collect_in_M_4p :
  assumes
    Qfm : "Q_fm  formula" and
    Qarty : "arity(Q_fm) = 5" and
    params_M : "a1M" "a2M" "a3M" "a4M" and
    Qsats : "x. xM  sats(M,Q_fm,[x,a1,a2,a3,a4])  is_Q(##M,x,a1,a2,a3,a4)" and
    Qabs  : "x. xM  is_Q(##M,x,a1,a2,a3,a4)  Q(x,a1,a2,a3,a4)" and
    "AM"
  shows
    "Collect(A,λx. Q(x,a1,a2,a3,a4))M" 
proof -
  have "zA  zM" for z
    using AM transitivity[of z A] by simp
  then
  have 1:"Collect(A,λx. is_Q(##M,x,a1,a2,a3,a4)) = Collect(A,λx. Q(x,a1,a2,a3,a4))" 
    using Qabs Collect_cong[of "A" "A" "λx. is_Q(##M,x,a1,a2,a3,a4)" "λx. Q(x,a1,a2,a3,a4)"] 
    by simp
  have "separation(##M,λx. is_Q(##M,x,a1,a2,a3,a4))"
    using separation_ax Qsats Qarty Qfm params_M
      separation_cong[of "##M" "λx. sats(M,Q_fm,[x,a1,a2,a3,a4])" 
        "λx. is_Q(##M,x,a1,a2,a3,a4)"]
    by simp
  then 
  have "Collect(A,λx. is_Q(##M,x,a1,a2,a3,a4))M"
    using separation_closed AM by simp 
  then
  show ?thesis using 1 by simp
qed

lemma Repl_in_M :
  assumes
    f_fm:  "f_fm  formula" and
    f_ar:  "arity(f_fm) 2 #+ length(env)" and
    fsats: "x y. xM  yM  sats(M,f_fm,[x,y]@env)  is_f(x,y)" and
    fabs:  "x y. xM  yM  is_f(x,y)  y = f(x)" and
    fclosed: "x. xA  f(x)  M"  and
    "AM" "envlist(M)" 
  shows "{f(x). xA}M"
proof -
  have "strong_replacement(##M, λx y. sats(M,f_fm,[x,y]@env))"
    using replacement_ax f_fm f_ar envlist(M) by simp
  then
  have "strong_replacement(##M, λx y. y = f(x))"
    using fsats fabs 
      strong_replacement_cong[of "##M" "λx y. sats(M,f_fm,[x,y]@env)" "λx y. y = f(x)"]
    by simp
  then
  have "{ y . xA , y = f(x) }  M" 
    using AM fclosed strong_replacement_closed by simp
  moreover
  have "{f(x). xA} = { y . xA , y = f(x) }"
    by auto
  ultimately show ?thesis by simp
qed

end (* M_ctm *)      

subsection‹A forcing locale and generic filters›
locale forcing_data = forcing_notion + M_ctm +
  assumes P_in_M:           "P  M"
    and leq_in_M:         "leq  M"

begin

lemma transD : "Transset(M)  y  M  y  M" 
  by (unfold Transset_def, blast) 

(* P ⊆ M *)
lemmas P_sub_M = transD[OF trans_M P_in_M]

definition
  M_generic :: "io" where
  "M_generic(G)  filter(G)  (DM. DP  dense(D)DG0)"

lemma M_genericD [dest]: "M_generic(G)  xG  xP"
  unfolding M_generic_def by (blast dest:filterD)

lemma M_generic_leqD [dest]: "M_generic(G)  pG  qP  pq  qG"
  unfolding M_generic_def by (blast dest:filter_leqD)

lemma M_generic_compatD [dest]: "M_generic(G)  pG  rG  qG. qp  qr"
  unfolding M_generic_def by (blast dest:low_bound_filter)

lemma M_generic_denseD [dest]: "M_generic(G)  dense(D)  DP  DM  qG. qD"
  unfolding M_generic_def by blast

lemma G_nonempty: "M_generic(G)  G0"
proof -
  have "PP" ..
  assume
    "M_generic(G)"
  with P_in_M P_dense PP show
    "G  0"
    unfolding M