Theory Discipline_Base

theory Discipline_Base
  imports
    "ZF-Constructible.Rank"
    M_Basic_No_Repl
    Relativization
    ZF_Miscellanea

begin

hide_const (open) Order.pred
declare [[syntax_ambiguity_warning = false]]

subsection‹Discipline of relativization of basic concepts›

definition
  is_singleton :: "[i⇒o,i,i] ⇒ o" where
  "is_singleton(A,x,z) ≡ ∃c[A]. empty(A,c) ∧ is_cons(A,x,c,z)"

lemma (in M_trivial) singleton_abs[simp] :
  "⟦ M(x) ; M(s) ⟧ ⟹ is_singleton(M,x,s) ⟷ s = {x}"
  unfolding is_singleton_def using nonempty by simp

synthesize "singleton" from_definition "is_singleton"
notation singleton_fm (‹⋅{_} is _⋅›)

lemmas (in M_trivial) singleton_closed = singleton_in_MI

lemma (in M_trivial) Upair_closed[simp]: "M(a) ⟹ M(b) ⟹ M(Upair(a,b))"
  using Upair_eq_cons by simp


text‹The following named theorems gather instances of transitivity
that arise from closure theorems›
named_theorems trans_closed

definition
  is_hcomp :: "[i⇒o,i⇒i⇒o,i⇒i⇒o,i,i] ⇒ o" where
  "is_hcomp(M,is_f,is_g,a,w) ≡ ∃z[M]. is_g(a,z) ∧ is_f(z,w)"

lemma (in M_trivial) is_hcomp_abs:
  assumes
    is_f_abs:"⋀a z. M(a) ⟹ M(z) ⟹ is_f(a,z) ⟷ z = f(a)" and
    is_g_abs:"⋀a z. M(a) ⟹ M(z) ⟹ is_g(a,z) ⟷ z = g(a)" and
    g_closed:"⋀a. M(a) ⟹ M(g(a))"
    "M(a)" "M(w)"
  shows
    "is_hcomp(M,is_f,is_g,a,w) ⟷ w = f(g(a))"
  unfolding is_hcomp_def using assms by simp

definition
  hcomp_fm :: "[i⇒i⇒i,i⇒i⇒i,i,i] ⇒ i" where
  "hcomp_fm(pf,pg,a,w) ≡ Exists(And(pg(succ(a),0),pf(0,succ(w))))"

lemma sats_hcomp_fm:
  assumes
    f_iff_sats:"⋀a b z. a∈nat ⟹ b∈nat ⟹ z∈M ⟹
                 is_f(nth(a,Cons(z,env)),nth(b,Cons(z,env))) ⟷ sats(M,pf(a,b),Cons(z,env))"
    and
    g_iff_sats:"⋀a b z. a∈nat ⟹ b∈nat ⟹ z∈M ⟹
                is_g(nth(a,Cons(z,env)),nth(b,Cons(z,env))) ⟷ sats(M,pg(a,b),Cons(z,env))"
    and
    "a∈nat" "w∈nat" "env∈list(M)"
  shows
    "sats(M,hcomp_fm(pf,pg,a,w),env) ⟷ is_hcomp(##M,is_f,is_g,nth(a,env),nth(w,env))"
proof -
  have "sats(M, pf(0, succ(w)), Cons(x, env)) ⟷ is_f(x,nth(w,env))" if "x∈M" "w∈nat" for x w
    using f_iff_sats[of 0 "succ(w)" x] that by simp
  moreover
  have "sats(M, pg(succ(a), 0), Cons(x, env)) ⟷ is_g(nth(a,env),x)" if "x∈M" "a∈nat" for x a
    using g_iff_sats[of "succ(a)" 0 x] that by simp
  ultimately
  show ?thesis unfolding hcomp_fm_def is_hcomp_def using assms by simp
qed


definition
  hcomp_r :: "[i⇒o,[i⇒o,i,i]⇒o,[i⇒o,i,i]⇒o,i,i] ⇒ o" where
  "hcomp_r(M,is_f,is_g,a,w) ≡ ∃z[M]. is_g(M,a,z) ∧ is_f(M,z,w)"

definition
  is_hcomp2_2 :: "[i⇒o,[i⇒o,i,i,i]⇒o,[i⇒o,i,i,i]⇒o,[i⇒o,i,i,i]⇒o,i,i,i] ⇒ o" where
  "is_hcomp2_2(M,is_f,is_g1,is_g2,a,b,w) ≡ ∃g1ab[M]. ∃g2ab[M].
       is_g1(M,a,b,g1ab) ∧ is_g2(M,a,b,g2ab) ∧ is_f(M,g1ab,g2ab,w)"

lemma (in M_trivial) hcomp_abs:
  assumes
    is_f_abs:"⋀a z. M(a) ⟹ M(z) ⟹ is_f(M,a,z) ⟷ z = f(a)" and
    is_g_abs:"⋀a z. M(a) ⟹ M(z) ⟹ is_g(M,a,z) ⟷ z = g(a)" and
    g_closed:"⋀a. M(a) ⟹ M(g(a))"
    "M(a)" "M(w)"
  shows
    "hcomp_r(M,is_f,is_g,a,w) ⟷ w = f(g(a))"
  unfolding hcomp_r_def using assms by simp

lemma hcomp_uniqueness:
  assumes
    uniq_is_f:
    "⋀r d d'. M(r) ⟹ M(d) ⟹ M(d') ⟹ is_f(M, r, d) ⟹ is_f(M, r, d') ⟹
               d = d'"
    and
    uniq_is_g:
    "⋀r d d'. M(r) ⟹ M(d) ⟹ M(d') ⟹ is_g(M, r, d) ⟹ is_g(M, r, d') ⟹
               d = d'"
    and
    "M(a)" "M(w)" "M(w')"
    "hcomp_r(M,is_f,is_g,a,w)"
    "hcomp_r(M,is_f,is_g,a,w')"
  shows
    "w=w'"
proof -
  from assms
  obtain z z' where "is_g(M, a, z)" "is_g(M, a, z')"
    "is_f(M,z,w)" "is_f(M,z',w')"
    "M(z)" "M(z')"
    unfolding hcomp_r_def by blast
  moreover from this and uniq_is_g and ‹M(a)›
  have "z=z'" by blast
  moreover note uniq_is_f and ‹M(w)› ‹M(w')›
  ultimately
  show ?thesis by blast
qed

lemma hcomp_witness:
  assumes
    wit_is_f: "⋀r. M(r) ⟹ ∃d[M]. is_f(M,r,d)" and
    wit_is_g: "⋀r. M(r) ⟹ ∃d[M]. is_g(M,r,d)" and
    "M(a)"
  shows
    "∃w[M]. hcomp_r(M,is_f,is_g,a,w)"
proof -
  from ‹M(a)› and wit_is_g
  obtain z where "is_g(M,a,z)" "M(z)" by blast
  moreover from this and wit_is_f
  obtain w where "is_f(M,z,w)" "M(w)" by blast
  ultimately
  show ?thesis
    using assms unfolding hcomp_r_def by auto
qed

― ‹In the next lemma, the absoluteness hypotheses on term‹g1› and term‹g2› can be restricted
to the actual parameters.›
lemma (in M_trivial) hcomp2_2_abs:
  assumes
    is_f_abs:"⋀r1 r2 z. M(r1) ⟹ M(r2) ⟹  M(z) ⟹ is_f(M,r1,r2,z) ⟷ z = f(r1,r2)" and
    is_g1_abs:"⋀r1 r2 z. M(r1) ⟹ M(r2) ⟹  M(z) ⟹ is_g1(M,r1,r2,z) ⟷ z = g1(r1,r2)" and
    is_g2_abs:"⋀r1 r2 z. M(r1) ⟹ M(r2) ⟹  M(z) ⟹ is_g2(M,r1,r2,z) ⟷ z = g2(r1,r2)" and
    types: "M(a)" "M(b)" "M(w)" "M(g1(a,b))" "M(g2(a,b))"
  shows
    "is_hcomp2_2(M,is_f,is_g1,is_g2,a,b,w) ⟷ w = f(g1(a,b),g2(a,b))"
  unfolding is_hcomp2_2_def
  using assms
  by simp

lemma hcomp2_2_uniqueness:
  assumes
    uniq_is_f:
    "⋀r1 r2 d d'. M(r1) ⟹ M(r2) ⟹ M(d) ⟹ M(d') ⟹
        is_f(M, r1, r2 , d) ⟹ is_f(M, r1, r2, d') ⟹  d = d'"
    and
    uniq_is_g1:
    "⋀r1 r2 d d'. M(r1) ⟹ M(r2)⟹ M(d) ⟹ M(d') ⟹ is_g1(M, r1,r2, d) ⟹ is_g1(M, r1,r2, d') ⟹
               d = d'"
    and
    uniq_is_g2:
    "⋀r1 r2 d d'. M(r1) ⟹ M(r2)⟹ M(d) ⟹ M(d') ⟹ is_g2(M, r1,r2, d) ⟹ is_g2(M, r1,r2, d') ⟹
               d = d'"
    and
    "M(a)" "M(b)" "M(w)" "M(w')"
    "is_hcomp2_2(M,is_f,is_g1,is_g2,a,b,w)"
    "is_hcomp2_2(M,is_f,is_g1,is_g2,a,b,w')"
  shows
    "w=w'"
proof -
  from assms
  obtain z z' y y' where "is_g1(M, a,b, z)" "is_g1(M, a,b, z')"
    "is_g2(M, a,b, y)" "is_g2(M, a,b, y')"
    "is_f(M,z,y,w)" "is_f(M,z',y',w')"
    "M(z)" "M(z')" "M(y)" "M(y')"
    unfolding is_hcomp2_2_def by force
  moreover from this and uniq_is_g1 uniq_is_g2 and ‹M(a)› ‹M(b)›
  have "z=z'" "y=y'" by blast+
  moreover note uniq_is_f and ‹M(w)› ‹M(w')›
  ultimately
  show ?thesis by blast
qed

lemma hcomp2_2_witness:
  assumes
    wit_is_f: "⋀r1 r2. M(r1) ⟹ M(r2) ⟹ ∃d[M]. is_f(M,r1,r2,d)" and
    wit_is_g1: "⋀r1 r2. M(r1) ⟹ M(r2) ⟹ ∃d[M]. is_g1(M,r1,r2,d)" and
    wit_is_g2: "⋀r1 r2. M(r1) ⟹ M(r2) ⟹ ∃d[M]. is_g2(M,r1,r2,d)" and
    "M(a)" "M(b)"
  shows
    "∃w[M]. is_hcomp2_2(M,is_f,is_g1,is_g2,a,b,w)"
proof -
  from ‹M(a)› ‹M(b)› and wit_is_g1
  obtain g1a where "is_g1(M,a,b,g1a)" "M(g1a)" by blast
  moreover from ‹M(a)› ‹M(b)› and wit_is_g2
  obtain g2a where "is_g2(M,a,b,g2a)" "M(g2a)" by blast
  moreover from calculation and wit_is_f
  obtain w where "is_f(M,g1a,g2a,w)" "M(w)" by blast
  ultimately
  show ?thesis
    using assms unfolding is_hcomp2_2_def by auto
qed

lemma (in M_trivial) extensionality_trans:
  assumes
    "M(d) ∧ (∀x[M]. x∈d  ⟷ P(x))"
    "M(d') ∧ (∀x[M]. x∈d' ⟷ P(x))"
  shows
    "d=d'"
proof -
  from assms
  have "∀x. x∈d ⟷ P(x) ∧ M(x)"
    using transM[of _ d] by auto
  moreover from assms
  have  "∀x. x∈d' ⟷ P(x) ∧ M(x)"
    using transM[of _ d'] by auto
  ultimately
  show ?thesis by auto
qed

definition
  lt_rel :: "[i⇒o,i,i] ⇒ o" where
  "lt_rel(M,a,b) ≡ a∈b ∧ ordinal(M,b)"

lemma (in M_trans) lt_abs[absolut]: "M(a) ⟹ M(b) ⟹ lt_rel(M,a,b) ⟷ a<b"
  unfolding lt_rel_def lt_def by auto

definition
  le_rel :: "[i⇒o,i,i] ⇒ o" where
  "le_rel(M,a,b) ≡ ∃sb[M]. successor(M,b,sb) ∧ lt_rel(M,a,sb)"

lemma (in M_trivial) le_abs[absolut]: "M(a) ⟹ M(b) ⟹ le_rel(M,a,b) ⟷ a≤b"
  unfolding le_rel_def by (simp add:absolut)

subsection‹Discipline for term‹Pow››

definition
  is_Pow :: "[i⇒o,i,i] ⇒ o" where
  "is_Pow(M,A,z) ≡ M(z) ∧ (∀x[M]. x ∈ z ⟷ subset(M,x,A))"

definition
  Pow_rel :: "[i⇒o,i] ⇒ i" (‹Pow⇗_⇖'(_')›) where
  "Pow_rel(M,r) ≡ THE d. is_Pow(M,r,d)"

abbreviation
  Pow_r_set ::  "[i,i] ⇒ i" (‹Pow⇗_⇖'(_')›) where
  "Pow_r_set(M) ≡ Pow_rel(##M)"

context M_basic_no_repl
begin

lemma is_Pow_uniqueness:
  assumes
    "M(r)"
    "is_Pow(M,r,d)" "is_Pow(M,r,d')"
  shows
    "d=d'"
  using assms extensionality_trans
  unfolding is_Pow_def
  by simp

lemma is_Pow_witness: "M(r) ⟹ ∃d[M]. is_Pow(M,r,d)"
  using power_ax unfolding power_ax_def powerset_def is_Pow_def
  by simp ― ‹We have to do this by hand, using axioms›

lemma is_Pow_closed : "⟦ M(r);is_Pow(M,r,d) ⟧ ⟹ M(d)"
  unfolding is_Pow_def by simp

lemma Pow_rel_closed[intro,simp]: "M(r) ⟹ M(Pow_rel(M,r))"
  unfolding Pow_rel_def
  using is_Pow_closed theI[OF ex1I[of "λd. is_Pow(M,r,d)"], OF _ is_Pow_uniqueness[of r]]
    is_Pow_witness
  by fastforce

lemmas trans_Pow_rel_closed[trans_closed] = transM[OF _ Pow_rel_closed]

text‹The proof of term‹f_rel_iff› lemma is schematic and it can reused by copy-paste
     replacing appropriately.›

lemma Pow_rel_iff:
  assumes "M(r)"  "M(d)"
  shows "is_Pow(M,r,d) ⟷ d = Pow_rel(M,r)"
proof (intro iffI)
  assume "d = Pow_rel(M,r)"
  with assms
  show "is_Pow(M, r, d)"
    using is_Pow_uniqueness[of r] is_Pow_witness
      theI[OF ex1I[of "λd. is_Pow(M,r,d)"], OF _ is_Pow_uniqueness[of r]]
    unfolding Pow_rel_def
    by auto
next
  assume "is_Pow(M, r, d)"
  with assms
  show "d = Pow_rel(M,r)"
    using is_Pow_uniqueness unfolding Pow_rel_def
    by (auto del:the_equality intro:the_equality[symmetric])
qed

text‹The next "def\_" result really corresponds to @{thm [source] Pow_iff}›
lemma def_Pow_rel: "M(A) ⟹ M(r) ⟹ A∈Pow_rel(M,r) ⟷ A ⊆ r"
  using Pow_rel_iff[OF _ Pow_rel_closed, of r r]
  unfolding is_Pow_def by simp

lemma Pow_rel_char: "M(r) ⟹ Pow_rel(M,r) = {A∈Pow(r). M(A)}"
proof -
  assume "M(r)"
  moreover from this
  have "x ∈ Pow_rel(M,r) ⟹ x⊆r" "M(x) ⟹ x ⊆ r ⟹ x ∈ Pow_rel(M,r)" for x
    using def_Pow_rel by (auto intro!:trans_Pow_rel_closed)
  ultimately
  show ?thesis
    using trans_Pow_rel_closed by blast
qed

lemma mem_Pow_rel_abs: "M(a) ⟹ M(r) ⟹ a ∈ Pow_rel(M,r) ⟷ a ∈ Pow(r)"
  using Pow_rel_char by simp

end ― ‹locale‹M_basic_no_repl››

subsection‹Discipline for term‹PiP››

definition
  PiP_rel:: "[i⇒o,i,i]⇒o" where
  "PiP_rel(M,A,f) ≡ ∃df[M]. is_domain(M,f,df) ∧ subset(M,A,df) ∧
                             is_function(M,f)"

context M_basic
begin

lemma def_PiP_rel:
  assumes
    "M(A)" "M(f)"
  shows
    "PiP_rel(M,A,f) ⟷ A ⊆ domain(f) ∧ function(f)"
  using assms unfolding PiP_rel_def by simp

end ― ‹locale‹M_basic››

definition
  Sigfun :: "[i,i⇒i]⇒i"  where
  "Sigfun(x,B) ≡ ⋃y∈B(x). {⟨x,y⟩}"

lemma SigFun_char : "Sigfun(x,B) = {x}×B(x)"
  unfolding Sigfun_def by auto

lemma Sigma_Sigfun: "Sigma(A,B) = ⋃ {Sigfun(x,B) . x∈A}"
  unfolding Sigma_def Sigfun_def ..

definition ― ‹Note that $B$ below is a higher order argument›
  is_Sigfun :: "[i⇒o,i,i⇒i,i]⇒o"  where
  "is_Sigfun(M,x,B,Sd) ≡ M(Sd) ∧ (∃RB[M]. is_Replace(M,B(x),λy z. z={⟨x,y⟩},RB)
                         ∧ big_union(M,RB,Sd))"

context M_trivial
begin

lemma is_Sigfun_abs:
  assumes
    "strong_replacement(M,λy z. z={⟨x,y⟩})"
    "M(x)" "M(B(x))" "M(Sd)"
  shows
    "is_Sigfun(M,x,B,Sd) ⟷ Sd = Sigfun(x,B)"
proof -
  have "⋃{z . y ∈ B(x), z = {⟨x, y⟩}} = (⋃y∈B(x). {⟨x, y⟩})" by auto
  then
  show ?thesis
    using assms transM[OF _ ‹M(B(x))›] Replace_abs
    unfolding is_Sigfun_def Sigfun_def by auto
qed

lemma Sigfun_closed:
  assumes
    "strong_replacement(M, λy z. y ∈ B(x) ∧ z = {⟨x, y⟩})"
    "M(x)" "M(B(x))"
  shows
    "M(Sigfun(x,B))"
  using assms transM[OF _ ‹M(B(x))›] RepFun_closed2
  unfolding Sigfun_def by simp

lemmas trans_Sigfun_closed[trans_closed] = transM[OF _ Sigfun_closed]

end ― ‹locale‹M_trivial››

definition
  is_Sigma :: "[i⇒o,i,i⇒i,i]⇒o"  where
  "is_Sigma(M,A,B,S) ≡ M(S) ∧ (∃RSf[M].
      is_Replace(M,A,λx z. z=Sigfun(x,B),RSf) ∧ big_union(M,RSf,S))"

locale M_Pi = M_basic +
  assumes
    Pi_separation: "M(A) ⟹ separation(M, PiP_rel(M,A))"
    and
    Pi_replacement:
    "M(x) ⟹ M(y) ⟹
      strong_replacement(M, λya z. ya ∈ y ∧ z = {⟨x, ya⟩})"
    "M(y) ⟹
      strong_replacement(M, λx z. z = (⋃xa∈y. {⟨x, xa⟩}))"

locale M_Pi_assumptions = M_Pi +
  fixes A B
  assumes
    Pi_assumptions:
    "M(A)"
    "⋀x. x∈A ⟹  M(B(x))"
    "∀x∈A. strong_replacement(M, λy z. y ∈ B(x) ∧ z = {⟨x, y⟩})"
    "strong_replacement(M,λx z. z=Sigfun(x,B))"
begin

lemma Sigma_abs[simp]:
  assumes
    "M(S)"
  shows
    "is_Sigma(M,A,B,S) ⟷ S = Sigma(A,B)"
proof -
  have "⋃{z . x ∈ A, z = Sigfun(x, B)} = (⋃x∈A. Sigfun(x, B))"
    by auto
  with assms
  show ?thesis
    using Replace_abs[of A _ "λx z. z=Sigfun(x,B)"]
      Sigfun_closed Sigma_Sigfun transM[of _ A]
      Pi_assumptions is_Sigfun_abs
    unfolding is_Sigma_def by simp
qed

lemma Sigma_closed[intro,simp]: "M(Sigma(A,B))"
proof -
  have "(⋃x∈A. Sigfun(x, B)) = ⋃{z . x ∈ A, z = Sigfun(x, B)}"
    by auto
  then
  show ?thesis
    using Sigma_Sigfun[of A B] transM[of _ A] Sigfun_closed Pi_assumptions
    by simp
qed

lemmas trans_Sigma_closed[trans_closed] = transM[OF _ Sigma_closed]

end ― ‹locale‹M_Pi_assumptions››

subsection‹Discipline for term‹Pi››

definition ― ‹completely relational›
  is_Pi :: "[i⇒o,i,i⇒i,i]⇒o"  where
  "is_Pi(M,A,B,I) ≡ M(I) ∧ (∃S[M]. ∃PS[M]. is_Sigma(M,A,B,S) ∧
       is_Pow(M,S,PS) ∧
       is_Collect(M,PS,PiP_rel(M,A),I))"

definition
  Pi_rel :: "[i⇒o,i,i⇒i] ⇒ i"  (‹Pi⇗_⇖'(_,_')›) where
  "Pi_rel(M,A,B) ≡ THE d. is_Pi(M,A,B,d)"

abbreviation
  Pi_r_set ::  "[i,i,i⇒i] ⇒ i" (‹Pi⇗_⇖'(_,_')›) where
  "Pi_r_set(M,A,B) ≡ Pi_rel(##M,A,B)"

context M_basic
begin

lemmas Pow_rel_iff = mbnr.Pow_rel_iff
lemmas Pow_rel_char = mbnr.Pow_rel_char
lemmas mem_Pow_rel_abs = mbnr.mem_Pow_rel_abs
lemmas Pow_rel_closed = mbnr.Pow_rel_closed
lemmas def_Pow_rel = mbnr.def_Pow_rel
lemmas trans_Pow_rel_closed = mbnr.trans_Pow_rel_closed

end ― ‹locale‹M_basic››

context M_Pi_assumptions
begin

lemma is_Pi_uniqueness:
  assumes
    "is_Pi(M,A,B,d)" "is_Pi(M,A,B,d')"
  shows
    "d=d'"
  using assms Pi_assumptions extensionality_trans
    Pow_rel_iff
  unfolding is_Pi_def by simp


lemma is_Pi_witness: "∃d[M]. is_Pi(M,A,B,d)"
  using Pow_rel_iff Pi_separation Pi_assumptions
  unfolding is_Pi_def by simp

lemma is_Pi_closed : "is_Pi(M,A,B,d) ⟹ M(d)"
  unfolding is_Pi_def by simp

lemma Pi_rel_closed[intro,simp]:  "M(Pi_rel(M,A,B))"
proof -
  have "is_Pi(M, A, B, THE xa. is_Pi(M, A, B, xa))"
    using Pi_assumptions
      theI[OF ex1I[of "is_Pi(M,A,B)"], OF _ is_Pi_uniqueness]
      is_Pi_witness is_Pi_closed
    by auto
  then show ?thesis
    using is_Pi_closed
    unfolding Pi_rel_def
    by simp
qed

― ‹From this point on, the higher order variable term‹B› must be
explicitly instantiated, and proof methods are slower›

lemmas trans_Pi_rel_closed[trans_closed] = transM[OF _ Pi_rel_closed]

lemma Pi_rel_iff:
  assumes "M(d)"
  shows "is_Pi(M,A,B,d) ⟷ d = Pi_rel(M,A,B)"
proof (intro iffI)
  assume "d = Pi_rel(M,A,B)"
  moreover
  note assms
  moreover from this
  obtain e where "M(e)" "is_Pi(M,A,B,e)"
    using is_Pi_witness by blast
  ultimately
  show "is_Pi(M, A, B, d)"
    using is_Pi_uniqueness is_Pi_witness is_Pi_closed
      theI[OF ex1I[of "is_Pi(M,A,B)"], OF _ is_Pi_uniqueness, of e]
    unfolding Pi_rel_def
    by simp
next
  assume "is_Pi(M, A, B, d)"
  with assms
  show "d = Pi_rel(M,A,B)"
    using is_Pi_uniqueness is_Pi_closed unfolding Pi_rel_def
    by (blast del:the_equality intro:the_equality[symmetric])
qed

lemma def_Pi_rel:
  "Pi_rel(M,A,B) = {f∈Pow_rel(M,Sigma(A,B)). A⊆domain(f) ∧ function(f)}"
proof -
  have "Pi_rel(M,A, B) ⊆ Pow_rel(M,Sigma(A,B))"
    using Pi_assumptions Pi_rel_iff[of "Pi_rel(M,A,B)"] Pow_rel_iff
    unfolding is_Pi_def by auto
  moreover
  have "f ∈ Pi_rel(M,A, B) ⟹ A⊆domain(f) ∧ function(f)" for f
    using Pi_assumptions Pi_rel_iff[of "Pi_rel(M,A,B)"]
      def_PiP_rel[of A f] trans_closed Pow_rel_iff
    unfolding is_Pi_def by simp
  moreover
  have "f ∈ Pow_rel(M,Sigma(A,B)) ⟹ A⊆domain(f) ∧ function(f) ⟹ f ∈ Pi_rel(M,A, B)" for f
    using Pi_rel_iff[of "Pi_rel(M,A,B)"] Pi_assumptions
      def_PiP_rel[of A f] trans_closed Pow_rel_iff
    unfolding is_Pi_def by simp
  ultimately
  show ?thesis by force
qed

lemma Pi_rel_char: "Pi_rel(M,A,B) = {f∈Pi(A,B). M(f)}"
  using Pi_assumptions def_Pi_rel Pow_rel_char[OF Sigma_closed] unfolding Pi_def
  by fastforce

lemma mem_Pi_rel_abs:
  assumes "M(f)"
  shows  "f ∈ Pi_rel(M,A,B) ⟷ f ∈ Pi(A,B)"
  using assms Pi_rel_char by simp

end ― ‹locale‹M_Pi_assumptions››

text‹The next locale (and similar ones below) are used to
show the relationship between versions of simple (i.e.
$\Sigma_1^{\mathit{ZF}}$, $\Pi_1^{\mathit{ZF}}$) concepts in two
different transitive models.›
locale M_N_Pi_assumptions = M:M_Pi_assumptions + N:M_Pi_assumptions N for N +
  assumes
    M_imp_N:"M(x) ⟹ N(x)"
begin

lemma Pi_rel_transfer: "Pi⇗M⇖(A,B) ⊆ Pi⇗N⇖(A,B)"
  using  M.Pi_rel_char N.Pi_rel_char M_imp_N by auto

end ― ‹locale‹M_N_Pi_assumptions››


locale M_Pi_assumptions_0 = M_Pi_assumptions _ 0
begin

text‹This is used in the proof of term‹AC_Pi_rel››
lemma Pi_rel_empty1[simp]: "Pi⇗M⇖(0,B) = {0}"
  using Pi_assumptions Pow_rel_char
  by (unfold def_Pi_rel function_def) (auto)

end ― ‹locale‹M_Pi_assumptions_0››

context M_Pi_assumptions
begin

subsection‹Auxiliary ported results on term‹Pi_rel›, now unused›
lemma Pi_rel_iff':
  assumes types:"M(f)"
  shows
    "f ∈ Pi_rel(M,A,B) ⟷ function(f) ∧ f ⊆ Sigma(A,B) ∧ A ⊆ domain(f)"
  using assms Pow_rel_char
  by (simp add:def_Pi_rel, blast)


lemma lam_type_M:
  assumes "M(A)" "⋀x. x∈A ⟹  M(B(x))"
    "⋀x. x ∈ A ⟹ b(x)∈B(x)" "strong_replacement(M,λx y. y=⟨x, b(x)⟩) "
  shows "(λx∈A. b(x)) ∈ Pi_rel(M,A,B)"
proof (auto simp add: lam_def def_Pi_rel function_def)
  from assms
  have "M({⟨x, b(x)⟩ . x ∈ A})"
    using Pi_assumptions transM[OF _ ‹M(A)›]
    by (rule_tac RepFun_closed, auto intro!:transM[OF _ ‹⋀x. x∈A ⟹  M(B(x))›])
  with assms
  show "{⟨x, b(x)⟩ . x ∈ A} ∈ Pow⇗M⇖(Sigma(A, B))"
    using Pow_rel_char by auto
qed

end ― ‹locale‹M_Pi_assumptions››

locale M_Pi_assumptions2 = M_Pi_assumptions +
  PiC: M_Pi_assumptions _ _ C for C
begin

lemma Pi_rel_type:
  assumes "f ∈ Pi⇗M⇖(A,C)" "⋀x. x ∈ A ⟹ f`x ∈ B(x)"
    and types: "M(f)"
  shows "f ∈ Pi⇗M⇖(A,B)"
  using assms Pi_assumptions
  by (simp only: Pi_rel_iff' PiC.Pi_rel_iff')
    (blast dest: function_apply_equality)

lemma Pi_rel_weaken_type:
  assumes "f ∈ Pi⇗M⇖(A,B)" "⋀x. x ∈ A ⟹ B(x) ⊆ C(x)"
    and types: "M(f)"
  shows "f ∈ Pi⇗M⇖(A,C)"
  using assms Pi_assumptions
  by (simp only: Pi_rel_iff' PiC.Pi_rel_iff')
    (blast intro: Pi_rel_type  dest: apply_type)

end ― ‹locale‹M_Pi_assumptions2››

end