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
    Arities
    Renaming_Auto
    Discipline_Function
begin

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=
  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  env  list(M) 
                    arity(φ)  1 #+ length(env) 
                    separation(##M,λx. sats(M,φ,[x] @ env))" and
    replacement_ax:"φ  formula  env  list(M) 
                    arity(φ)  2 #+ length(env) 
                    strong_replacement(##M,λx y. sats(M,φ,[x,y] @ env))"

locale M_ZF_trans= M_ZF +
  assumes
    trans_M:       "Transset(M)"
begin

lemmas transitivity= Transset_intf[OF trans_M]

subsection‹Interface with termM_trivial

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
  then
  have "z=0"
    using transitivity empty_def by auto
  with zm show ?thesis 
    by simp
qed

end (* M_ZF_trans *)

locale M_ZFC= M_ZF +
  assumes
    choice_ax:"choice_ax(##M)"

locale M_ZFC_trans= M_ZF_trans + M_ZFC

sublocale M_ZF_trans  M_trans "##M"
  using transitivity zero_in_M exI[of "λx. xM"]
  by unfold_locales simp_all

sublocale M_ZF_trans  M_trivial "##M"
  using trans_M upair_ax Union_ax by unfold_locales

subsection‹Interface with termM_basic

(* Inter_separation: "M(A) ⟹ separation(M, λx. ∀ y[M]. y∈A ⟹ x∈y)" *)
definition Intersection where
 "Intersection(N,B,x)  (y[N]. yB  xy)"

manual_schematic "Inter_fm" for "Intersection"
  unfolding Intersection_def 
  by (rule sep_rules | simp)+
synthesize "Intersection" from_schematic Inter_fm
arity_theorem for "Intersection_fm" 

context M_ZF_trans
begin

lemma inter_sep_intf :
  assumes
    "AM"
  shows
    "separation(##M,λx . yM . yA  xy)"
proof -
  have "arity(Intersection_fm(1,0)) = 2" "0nat" "1nat" 
    using arity_Intersection_fm pred_Un_distrib by auto
  then
    have "aM. separation(##M, λx. sats(M,Intersection_fm(1,0) , [x, a]))"
      using separation_ax Intersection_fm_type
      by simp
  moreover
  have "(yM . ya  xy)  sats(M,Intersection_fm(1,0),[x,a])"
    if "aM" "xM" for a x
    using that Intersection_iff_sats[of 1 "[x,a]" a 0 x M] 
    unfolding Intersection_def 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: ord_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_definitions ord_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_definitions ord_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_definitions ord_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_definitions ord_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_definitions ord_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_definitions ord_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_definitions ord_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_definitions ord_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_definitions ord_simp_union)
  (* "fsfm(0,1,2)≡(⋅∃(⋅∃(⋅∃(⋅∃⋅pair_fm(3, 2, 4) ∧ ⋅pair_fm(6, 2, 1) ∧ ⋅cons_fm(1, 3, 0) ∧ ⋅{0,0} is 5 ⋅⋅⋅⋅⋅)⋅)⋅)⋅)" for i j k *)
  then
  have "n0M. strong_replacement(##M, λp z. sats(M,fsfm(0,1,2) , [p,z,n0]))"
    using replacement_ax[of "fsfm(0,1,2)"] 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

end (* M_ZF_trans *)

sublocale M_ZF_trans  M_basic "##M"
  using trans_M zero_in_M power_ax M_basic_sep_instances funspace_succ_rep_intf
  by unfold_locales auto

subsection‹Interface with termM_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_definitions ord_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
    "i  nat" "j  nat" "env  list(A)"
  shows
    "tran_closure(##A,nth(i,env),nth(j,env))  sats(A,?tc(i,j),env)"
  unfolding tran_closure_def
  by (insert assms ; (rule sep_rules rtran_closure_fm_auto | simp))+

synthesize "trans_closure" from_schematic trans_closure_fm_auto

lemma arity_tran_closure_fm :
  "xnat;fnat  arity(trans_closure_fm(x,f)) = succ(x)  succ(f)"
  unfolding trans_closure_fm_def
  using arity_omega_fm arity_field_fm arity_typed_function_fm arity_pair_fm arity_empty_fm arity_fun_apply_fm
    arity_composition_fm arity_succ_fm union_abs2 pred_Un_distrib
  by 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_iff_sats | simp)+)

context M_ZF_trans
begin

lemma 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_definitions
    by (simp del:FOL_sats_iff pair_abs add: ord_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

text‹Proof that term‹nat  M

lemma 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: 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 nat_subset_I' :
  " IM ; 0I ; x. xI  succ(x)I   nat  I"
  by (rule subsetI,induct_tac x,simp+)

lemma 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 transitivity by simp
  then have "natI"
    using  IM 0I nat_subset_I' by simp
  then show ?thesis using IM by auto
qed

lemma 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 (* M_ZF_trans *)

sublocale M_ZF_trans  M_trancl "##M"
  using rtrancl_separation_intf wftrancl_separation_intf nat_in_M
    wellfounded_trancl_def by unfold_locales auto

subsection‹Interface with termM_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) 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_into_M by simp
    then have 1:"Memrel(succ(n))M"
      using nnat› Memrel_closed by simp
    have "0M"
      using  nat_0I nat_into_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 fm_definitions
      by (simp add:ord_simp_union)
    then
    have "strong_replacement(##M,λx z. sats(M,?f,[x,z,Memrel(succ(n)),A,0]))"
      using replacement_ax[of ?f] 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_into_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 fm_definitions
      using arty by (simp add:ord_simp_union)
    then
    have "strong_replacement(##M,λx z. sats(M,?f,[x,z,Memrel(succ(n)),v]))"
      using replacement_ax[of ?f] 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_into_M by simp
  have 1:"arity(formula_functor_fm(1,0)) = 2"
    unfolding fm_definitions
    by (simp add:ord_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[where is_F_fm="formula_functor_fm(1,0)"] 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 fm_definitions by (simp add:ord_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[where is_F_fm="tl_fm(1,0)"] 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 fm_definitions by (simp add:ord_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[where is_F_fm="big_union_fm(1,0)"] 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_into_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 fm_definitions
    by (simp add:ord_simp_union)
  then
  have "strong_replacement(##M,λn y. sats(M,?f,[n,y,A,0,nat]))"
    using replacement_ax[of ?f] 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_into_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 fm_definitions
    by (simp add:ord_simp_union)
  then
  have "strong_replacement(##M,λn y. sats(M,?f,[n,y,0,nat]))"
    using replacement_ax[of ?f] 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 fm_definitions
    by (simp add:ord_simp_union)
  then
  have "strong_replacement(##M,λn y. sats(M,?f,[n,y,A,nat]))"
    using replacement_ax[of ?f] 1 artyf AM nat_in_M by simp
  then
  show ?thesis using repl_sats[of M ?f "[A,nat]"]  satsf  by simp
qed

sublocale M_ZF_trans  M_datatypes "##M"
  using list_repl1_intf list_repl2_intf formula_repl1_intf
    formula_repl2_intf nth_repl_intf
  by unfold_locales auto

sublocale M_ZF_trans  M_eclose "##M"
  using eclose_repl1_intf eclose_repl2_intf
  by unfold_locales auto

(* 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

declare is_powapply_fm_def[fm_definitions add]

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 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_definitions ord_simp_union)
  then
  have "f0M. strong_replacement(##M, λp z. sats(M,is_powapply_fm(2,0,1) , [p,z,f0]))"
    using replacement_ax[of "is_powapply_fm(2,0,1)"] 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 :
  " 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_definitions ord_simp_union)
  then
  have "f0M. strong_replacement(##M, λp z. sats(M,PHrank_fm(2,0,1) , [p,z,f0]))"
    using replacement_ax[of "PHrank_fm(2,0,1)"] by simp
  then
  have "f0M. strong_replacement(##M, PHrank(##M,f0))"
    unfolding strong_replacement_def univalent_def by (simp add:sats_PHrank_fm)
  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 :
  " 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 add:sats_PHrank_fm)

declare is_Hrank_fm_def[fm_definitions add]
declare PHrank_fm_def[fm_definitions add]
(* 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 add:sats_is_Hrank_fm)
  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 add:sats_is_Hrank_fm)
  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 fm_definitions
    by (simp add:ord_simp_union)
  then
  have "strong_replacement(##M,λx z. sats(M,?f,[x,z,rrank(X)]))"
    using replacement_ax[of ?f] 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)))))"
declare is_HVfrom_fm_def[fm_definitions add]

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 fm_definitions
      by (simp add:ord_simp_union)
    then
    have "strong_replacement(##M,λx z. sats(M,?f,[x,z,A,mesa]))"
      using replacement_ax[of ?f] 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

sublocale M_ZF_trans  M_eclose_pow "##M"
  using power_ax powapply_repl phrank_repl trans_repl_HVFrom
    wfrec_rank by unfold_locales auto

subsection‹Interface for proving Collects and Replace in M.›
context M_ZF_trans
begin

lemma Collect_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

― ‹This version has a weaker assumption.›
lemma separation_in_M :
  assumes
    "φ  formula" "envlist(M)"
    "arity(φ)  1 #+ length(env)" "AM" and
    satsQ: "x. xA  sats(M,φ,[x]@env)  Q(x)"
  shows
    "{yA . Q(y)}  M"
proof -
  let ?φ' = "And(φ,Member(0,length(env)#+1))"
  have "arity(?φ')  1 #+ length(env@[A])"
    using assms Un_le
      le_trans[of "arity(φ)" "1#+length(env)" "2#+length(env)"]
    by force
  moreover from assms
  have "?φ'formula"
    "nth(length(env), env @ [A]) = A" using assms nth_append by auto
  moreover from calculation
  have " x . x  M  sats(M,?φ',[x]@env@[A])  Q(x)  xA"
    using arity_sats_iff[of _ "[A]" _ "[_]@env"] assms
    by auto
  ultimately
  show ?thesis using assms
      Collect_in_M[of ?φ' "env@[A]" _ "λx . Q(x)  xA", OF _ _ _ AM]
    by auto
qed

lemma Replace_in_M :
  assumes
    f_fm:  "φ  formula" and
    f_ar:  "arity(φ) 2 #+ length(env)" and
    fsats: "x y. xA  yM  (M,[x,y]@env  φ)  y = f(x)" and
    fclosed: "x. xA  f(x)  M"  and
    "AM" "envlist(M)"
  shows "{f(x) . xA}M"
proof -
  let ?φ' = "And(φ,Member(0,length(env)#+2))"
  have "arity(?φ')  2 #+ length(env@[A])"
    using assms Un_le
      le_trans[of "arity(φ)" "2#+(length(env))" "3#+length(env)"]
    by force
  moreover from assms
  have "?φ'formula" "nth(length(env), env @ [A]) = A"
    using assms nth_append by auto
  moreover from calculation
  have " x y. x  M  yM  (M,[x,y]@env@[A]?φ')  y=f(x) xA"
    using arity_sats_iff[of _ "[A]" _ "[_,_]@env"] assms
    by auto
  moreover from calculation
  have "strong_replacement(##M, λx y. M,[x,y]@env@[A]  ?φ')"
    using replacement_ax[of ?φ'] envlist(M) assms by simp
  ultimately
  have 4:"strong_replacement(##M, λx y. y = f(x)  xA)"
    using
      strong_replacement_cong[of "##M" "λx y. M,[x,y]@env@[A]?φ'" "λx y. y = f(x)  xA"]
    by simp
  then
  have "{y . xA , y = f(x)}  M"
    using AM strong_replacement_closed[OF 4,of A] fclosed by simp
  moreover
  have "{f(x). xA} = { y . xA , y = f(x)}"
    by auto
  ultimately show ?thesis by simp
qed

lemma Replace_relativized_in_M :
  assumes
    f_fm:  "φ  formula" and
    f_ar:  "arity(φ) 2 #+ length(env)" and
    fsats: "x y. xA  yM  (M,[x,y]@env  φ)  is_f(x,y)" and
    fabs:  "x y. xA  yM  is_f(x,y)  y = f(x)" and
    fclosed: "x. xA  f(x)  M"  and
    "AM" "envlist(M)"
  shows "{f(x) . xA}M"
  using assms Replace_in_M[of φ] by auto

definition ρ_repl :: "ii" where
  "ρ_repl(l)  rsum({0, 1, 1, 0}, id(l), 2, 3, l)"

lemma f_type : "{0, 1, 1, 0}  2  3"
  using Pi_iff unfolding function_def by auto

lemma ren_type :
  assumes "lnat"
  shows "ρ_repl(l) : 2#+l  3#+l"
  using sum_type[of 2 3 l l "{0, 1, 1, 0}" "id(l)"] f_type assms id_type
  unfolding ρ_repl_def by auto

lemma ren_action :
  assumes
    "envlist(M)" "xM" "yM" "zM"
  shows " i . i < 2#+length(env) 
          nth(i,[x,z]@env) = nth(ρ_repl(length(env))`i,[z,x,y]@env)"
proof -
  let ?f="{0, 1, 1, 0}"
  have 1:"(j. j < length(env)  nth(j, env) = nth(id(length(env)) ` j, env))"
    using assms ltD by simp
  have 2:"nth(j, [x,z]) = nth(?f ` j, [z,x,y])" if "j<2" for j
  proof -
    consider "j=0" | "j=1" using  ltD[OF j<2] by auto
    then show ?thesis
    proof(cases)
      case 1
      then show ?thesis using apply_equality f_type by simp
    next
      case 2
      then show ?thesis using apply_equality f_type by simp
    qed
  qed
  show ?thesis
    using sum_action[OF _ _ _ _ f_type id_type _ _ _ _ _ _ _ 2 1,simplified] assms
    unfolding ρ_repl_def by simp
qed

lemma Lambda_in_M :
  assumes
    f_fm:  "φ  formula" and
    f_ar:  "arity(φ) 2 #+ length(env)" and
    fsats: "x y. xA  yM  (M,[x,y]@env  φ)  is_f(x,y)" and
    fabs:  "x y. xA  yM  is_f(x,y)  y = f(x)" and
    fclosed: "x. xA  f(x)  M" and
    "AM" "envlist(M)"
  shows "(λxA . f(x)) M"
  unfolding lam_def
proof -
  let ?ren="ρ_repl(length(env))"
  let ?j="2#+length(env)"
  let ?k="3#+length(env)"
  let ="ren(φ)`?j`?k`?ren"
  let ?φ'="Exists(And(pair_fm(1,0,2),))"
  let ?p="λx y. zM. pair(##M,x,z,y)  is_f(x,z)"
  have "?φ'formula" "formula"
    using env_ length_type f_fm ren_type ren_tc[of φ "2#+length(env)" "3#+length(env)" ?ren]
    by simp_all
  moreover from this
  have "arity()3#+(length(env))" "arity()nat"
    using assms arity_ren[OF f_fm _ _ ren_type,of "length(env)"] by simp_all
  then
  have "arity(?φ')  2#+(length(env))"
    using arity_pair_fm Un_le pred_Un_distrib assms pred_le
    by simp
  moreover from this calculation
  have "xA  yM  (M,[x,y]@env  ?φ')  ?p(x,y)" for x y
    using env_ length_type[OF env_] assms transitivity[OF _ AM]
      sats_iff_sats_ren[OF f_fm _ _ _ _ ren_type f_ar ren_action[rule_format,of _ x y],of _ M ]
    by auto
  moreover
  have "xA  yM  ?p(x,y)  y = <x,f(x)>" for x y
    using assms transitivity[OF _ A_] fclosed
    by simp
  moreover
  have " x . xA  <x,f(x)>  M"
    using transitivity[OF _ AM] pair_in_M_iff fclosed by simp
  ultimately
  show "{x,f(x) . xA }  M"
    using Replace_in_M[of ?φ'] AM env_
    by simp
qed

definition ρ_pair_repl :: "ii" where
  "ρ_pair_repl(l)  rsum({0, 0, 1, 1, 2, 3}, id(l), 3, 4, l)"

lemma f_type' : "{0,0 , 1, 1, 2, 3}  3  4"
  using Pi_iff unfolding function_def by auto

lemma ren_type' :
  assumes "lnat"
  shows "ρ_pair_repl(l) : 3#+l  4#+l"
  using sum_type[of 3 4 l l "{0, 0, 1, 1, 2, 3}" "id(l)"] f_type' assms id_type
  unfolding ρ_pair_repl_def by auto

lemma ren_action' :
  assumes
    "envlist(M)" "xM" "yM" "zM" "uM"
  shows " i . i < 3#+length(env) 
          nth(i,[x,z,u]@env) = nth(ρ_pair_repl(length(env))`i,[x,z,y,u]@env)"
proof -
  let ?f="{0, 0, 1, 1, 2,3}"
  have 1:"(j. j < length(env)  nth(j, env) = nth(id(length(env)) ` j, env))"
    using assms ltD by simp
  have 2:"nth(j, [x,z,u]) = nth(?f ` j, [x,z,y,u])" if "j<3" for j
  proof -
    consider "j=0" | "j=1" | "j=2" using  ltD[OF j<3] by auto
    then show ?thesis
    proof(cases)
      case 1
      then show ?thesis using apply_equality f_type' by simp
    next
      case 2
      then show ?thesis using apply_equality f_type' by simp
    next
      case 3
      then show ?thesis using apply_equality f_type' by simp
    qed
  qed
  show ?thesis
    using sum_action[OF _ _ _ _ f_type' id_type _ _ _ _ _ _ _ 2 1,simplified] assms
    unfolding ρ_pair_repl_def by simp
qed

lemma LambdaPair_in_M :
  assumes
    f_fm:  "φ  formula" and
    f_ar:  "arity(φ) 3 #+ length(env)" and
    fsats: "x z r. xM  zM  rM  (M,[x,z,r]@env  φ)  is_f(x,z,r)" and
    fabs:  "x z r. xM  zM  rM  is_f(x,z,r)  r = f(x,z)" and
    fclosed: "x z. xM  zM  f(x,z)  M" and
    "AM" "envlist(M)"
  shows "(λxA . f(fst(x),snd(x))) M"
proof -
  let ?ren="ρ_pair_repl(length(env))"
  let ?j="3#+length(env)"
  let ?k="4#+length(env)"
  let ="ren(φ)`?j`?k`?ren"
  let ?φ'="Exists(Exists(And(fst_fm(2,0),(And(snd_fm(2,1),)))))"
  let ?p="λx y. is_f(fst(x),snd(x),y)"
  have "?φ'formula" "formula"
    using env_ length_type f_fm ren_type' ren_tc[of φ ?j ?k ?ren]
    by simp_all
  moreover from this
  have "arity()4#+(length(env))" "arity()nat"
    using assms arity_ren[OF f_fm _ _ ren_type',of "length(env)"] by simp_all
  moreover from calculation
  have 1:"arity(?φ')  2#+(length(env))" "?φ'formula"
    using arity_fst_fm arity_snd_fm Un_le pred_Un_distrib assms pred_le
    by simp_all
  moreover from this calculation
  have 2:"xA  yM  (M,[x,y]@env  ?φ')  ?p(x,y)" for x y
    using
      sats_iff_sats_ren[OF f_fm _ _ _ _ ren_type' f_ar
         ren_action'[rule_format,of _ "fst(x)" x "snd(x)" y],simplified]
       env_ length_type[OF env_] transitivity[OF _ AM]
      fst_snd_closed pair_in_M_iff fsats[of "fst(x)" "snd(x)" y,symmetric]
      fst_abs snd_abs
    by auto
  moreover from assms
  have 3:"xA  yM  ?p(x,y)  y = f(fst(x),snd(x))" for x y
    using fclosed fst_snd_closed pair_in_M_iff fabs transitivity
    by auto
  moreover
  have 4:" x . xA  <x,f(fst(x),snd(x))>  M" " x . xA  f(fst(x),snd(x))  M"
    using transitivity[OF _ AM] pair_in_M_iff fclosed fst_snd_closed
    by simp_all
  ultimately
  show ?thesis
    using Lambda_in_M[of ?φ'] env_ A_ by simp
qed

end (* M_ZF_trans *)

end