Theory Separation_Axiom

section‹The Axiom of Separation in $M[G]$›
theory Separation_Axiom
  imports Forcing_Theorems Separation_Rename
begin

context G_generic
begin

lemma map_val :
  assumes "envlist(M[G])"
  shows "nenvlist(M). env = map(val(G),nenv)"
  using assms
  proof(induct env)
    case Nil
    have "map(val(G),Nil) = Nil" by simp
    then show ?case by force
  next
    case (Cons a l)
    then obtain a' l' where
      "l'  list(M)" "l=map(val(G),l')" "a = val(G,a')"
      "Cons(a,l) = map(val(G),Cons(a',l'))" "Cons(a',l')  list(M)"
      using aM[G] GenExtD
      by force
    then show ?case by force
qed


lemma Collect_sats_in_MG :
  assumes
    "cM[G]"
    "φ  formula" "envlist(M[G])" "arity(φ)  1 #+ length(env)"
  shows    
    "{xc. (M[G], [x] @ env  φ)} M[G]"
proof -  
  from cM[G]
  obtain π where "π  M" "val(G, π) = c"
    using GenExt_def by auto
  let ="And(Member(0,1 #+ length(env)),φ)" and ?Pl1="[P,leq,one]"
  let ?new_form="sep_ren(length(env),forces())"
  let ="Exists(Exists(And(pair_fm(0,1,2),?new_form)))"
  note phi = φformula arity(φ)  1 #+ length(env) 
  then
  have "formula" by simp
  with env_ phi
  have "arity()  2#+length(env) " 
    using nat_simp_union leI by simp
  with envlist(_) phi
  have "arity(forces())  6 #+ length(env)"
    using  arity_forces_le by simp
  then
  have "arity(forces())  7 #+ length(env)"
    using nat_simp_union arity_forces leI by simp
  with arity(forces()) 7 #+ _ env  _ φ  formula
  have "arity(?new_form)  7 #+ length(env)" "?new_form  formula"
    using arity_rensep[OF definability[of ""]]  definability[of ""] type_rensep 
    by auto
  then
  have "pred(pred(arity(?new_form)))  5 #+ length(env)" "formula"
    unfolding pair_fm_def upair_fm_def 
    using nat_simp_union length_type[OF envlist(M[G])] 
        pred_mono[OF _ pred_mono[OF _ arity(?new_form)  _]]
    by auto
  with arity(?new_form)  _ ?new_form  formula
  have "arity()  5 #+ length(env)"
    unfolding pair_fm_def upair_fm_def 
    using nat_simp_union arity_forces
    by auto
  from φformula
  have "forces()  formula"
    using definability by simp
  from πM P_in_M 
  have "domain(π)M" "domain(π) × P  M"
    by (simp_all flip:setclass_iff)
  from env  _
  obtain nenv where "nenvlist(M)" "env = map(val(G),nenv)" "length(nenv) = length(env)"
    using map_val by auto
  from arity(φ)  _ env_ φ_
  have "arity(φ)  2#+ length(env)" 
    using le_trans[OF arity(φ)_] add_le_mono[of 1 2,OF _ le_refl] 
    by auto
  with nenv_ env_ πM φ_ length(nenv) = length(env)
  have "arity()  length([θ] @ nenv @ [π])" for θ 
    using nat_union_abs2[OF _ _ arity(φ)  2#+ _] nat_simp_union 
    by simp    
  note in_M = πM domain(π) × P  M  P_in_M one_in_M leq_in_M
  {
    fix u
    assume "u  domain(π) × P" "u  M"
    with in_M ?new_form  formula formula nenv  _
    have Eq1: "(M, [u] @ ?Pl1 @ [π] @ nenv  )  
                        (θM. pP. u =θ,p  
                          M, [θ,p,u]@?Pl1@[π] @ nenv  ?new_form)"
      by (auto simp add: transitivity)
    have Eq3: "θM  pP 
       (M, [θ,p,u]@?Pl1@[π]@nenv  ?new_form) 
          (F. M_generic(F)  p  F  (M[F],  map(val(F), [θ] @ nenv@[π])   ))" 
      for θ p 
    proof -
      fix p θ 
      assume "θ  M" "pP"
      then 
      have "pM" using P_in_M by (simp add: transitivity)
      note in_M' = in_M θ  M pM u  domain(π) × P u  M nenv_
      then 
      have "[θ,u]  list(M)" by simp
      let ?env="[p]@?Pl1@[θ] @ nenv @ [π,u]"
      let ?new_env=" [θ,p,u,P,leq,one,π] @ nenv"
      let ="Exists(Exists(And(pair_fm(0,1,2),?new_form)))"
      have "[θ, p, u, π, leq, one, π]  list(M)" 
        using in_M' by simp
      have "  formula" "forces() formula"  
        using phi by simp_all
      from in_M' 
      have "?Pl1  list(M)" by simp
      from in_M' have "?env  list(M)" by simp
      have Eq1': "?new_env  list(M)" using in_M'  by simp 
      then 
      have "(M, [θ,p,u]@?Pl1@[π] @ nenv  ?new_form)  (M, ?new_env  ?new_form)"
        by simp
      from in_M' env  _ Eq1' length(nenv) = length(env) 
        arity(forces())  7 #+ length(env) forces() formula
        [θ, p, u, π, leq, one, π]  list(M) 
      have "...  M, ?env  forces()"
        using sepren_action[of "forces()"  "nenv",OF _ _ nenvlist(M)] 
        by simp
      also from in_M'
      have "...  M,  ([p,P, leq, one,θ]@nenv@ [π])@[u]  forces()" 
        using app_assoc by simp
      also 
      from in_M' env_ phi length(nenv) = length(env)
        arity(forces())  6 #+ length(env) forces()formula
      have "...  M,  [p,P, leq, one,θ]@ nenv @ [π]  forces()"        
        by (rule_tac arity_sats_iff,auto)
      also 
      from arity(forces())  6 #+ length(env) forces()formula in_M' phi 
      have " ...  (F. M_generic(F)  p  F  
                           M[F],  map(val(F), [θ] @ nenv @ [π])   )"
        using  definition_of_forcing 
      proof (intro iffI)
        assume a1: "M,  [p,P, leq, one,θ] @ nenv @ [π]   forces()"
        note definition_of_forcing arity(φ) 1#+_
        with nenv_ arity()  length([θ] @ nenv @ [π]) env_
        have "p  P  formula  [θ,π]  list(M) 
                  M, [p,P, leq, one] @ [θ]@ nenv@[π]  forces()  
              G. M_generic(G)  p  G  M[G],  map(val(G), [θ] @ nenv @[π])   "
          by auto
        then
        show "F. M_generic(F)  p  F  
                  M[F],  map(val(F), [θ] @ nenv @ [π])   "
          using  formula pP a1 θM πM by simp
      next
        assume "F. M_generic(F)  p  F  
                   M[F],  map(val(F), [θ] @ nenv @[π])   "
        with definition_of_forcing [THEN iffD2] arity()  length([θ] @ nenv @ [π])
        show "M,  [p, P, leq, one,θ] @ nenv @ [π]   forces()"
          using  formula pP in_M' 
          by auto
      qed
      finally 
      show "(M, [θ,p,u]@?Pl1@[π]@nenv  ?new_form)  (F. M_generic(F)  p  F  
                           M[F],  map(val(F), [θ] @ nenv @ [π])   )" 
        by simp
    qed
    with Eq1 
    have "(M, [u] @ ?Pl1 @ [π] @ nenv  )  
         (θM. pP. u =θ,p  
          (F. M_generic(F)  p  F  M[F],  map(val(F), [θ] @ nenv @ [π])   ))"
      by auto 
  }
  then 
  have Equivalence: "u domain(π) × P  u  M  
       (M, [u] @ ?Pl1 @ [π] @ nenv  )  
         (θM. pP. u =θ,p  
          (F. M_generic(F)  p  F  M[F],   map(val(F), [θ] @ nenv @[π])   ))" 
    for u 
    by simp
  moreover from env = _ πM nenvlist(M)
  have map_nenv:"map(val(G), nenv@[π]) = env @ [val(G,π)]"
    using map_app_distrib append1_eq_iff by auto
  ultimately
  have aux:"(θM. pP. u =θ,p  (pG  M[G], [val(G,θ)] @ env @ [val(G,π)]  ))" 
   (is "(θM. pP. _ ( _  _, ?vals(θ)  _))")
   if "u  domain(π) × P" "u  M"  "M, [u]@ ?Pl1 @[π] @ nenv  " for u
    using Equivalence[THEN iffD1, OF that] generic by force
  moreover 
  have "θM  val(G,θ)M[G]" for θ
    using GenExt_def by auto
  moreover
  have "θ M  [val(G, θ)] @ env @ [val(G, π)]  list(M[G])" for θ
  proof -
    from πM
    have "val(G,π) M[G]" using GenExtI by simp
    moreover
    assume "θ  M"
    moreover
    note env  list(M[G])
    ultimately
    show ?thesis 
      using GenExtI by simp
  qed
  ultimately 
  have "(θM. pP. u=θ,p  (pG  val(G,θ)nth(1 #+ length(env),[val(G, θ)] @ env @ [val(G, π)]) 
         M[G],  ?vals(θ)   φ))"
    if "u  domain(π) × P" "u  M"  "M, [u] @ ?Pl1 @[π] @ nenv  " for u
    using aux[OF that] by simp
  moreover from env  _ πM
  have nth:"nth(1 #+ length(env),[val(G, θ)] @ env @ [val(G, π)]) = val(G,π)" 
    if "θM" for θ
    using nth_concat[of "val(G,θ)" "val(G,π)" "M[G]"] using that GenExtI by simp
  ultimately
  have "(θM. pP. u=θ,p  (pG  val(G,θ)val(G,π)  M[G],  ?vals(θ)   φ))"
    if "u  domain(π) × P" "u  M"  "M, [u] @ ?Pl1 @[π] @ nenv  " for u
    using that πM env  _ by simp
  with domain(π)×PM
  have "udomain(π)×P . (M, [u] @ ?Pl1 @[π] @ nenv  )  (θM. pP. u =θ,p 
        (p  G  val(G, θ)val(G, π)  M[G],  ?vals(θ)   φ))"
    by (simp add:transitivity)
  then 
  have "{udomain(π)×P . (M,[u] @ ?Pl1 @[π] @ nenv  ) } 
     {udomain(π)×P . θM. pP. u =θ,p  
       (p  G  val(G, θ)val(G, π)  (M[G], ?vals(θ)  φ))}"
    (is "?n?m") 
    by auto
  with val_mono 
  have first_incl: "val(G,?n)  val(G,?m)" 
    by simp
  note  val(G,π) = c (* from the assumptions *)
  with formula  arity()  _ in_M nenv  _ env  _ length(nenv) = _ 
  have "?nM" 
    using separation_ax leI separation_iff by auto 
  from generic 
  have "filter(G)" "GP" 
    unfolding M_generic_def filter_def by simp_all
  from val(G,π) = c 
  have "val(G,?m) =
               {val(G,t) .. tdomain(π) , qP .  
                    (θM. pP. t,q = θ, p  
            (p  G  val(G, θ)  c  (M[G],  [val(G, θ)] @ env @ [c]   φ))  q  G)}"
    using val_of_name by auto
  also 
  have "... =  {val(G,t) .. tdomain(π) , qP. 
                   val(G, t)  c  (M[G],  [val(G, t)] @ env @ [c]   φ)  q  G}" 
  proof -

    have "tM 
      (qP. (θM. pP. t,q = θ, p  
              (p  G  val(G, θ)  c  (M[G],  [val(G, θ)] @ env @ [c]   φ))  q  G)) 
       
      (qP. val(G, t)  c  ( M[G], [val(G, t)]@env@[c] φ )  q  G)" for t
      by auto
    then show ?thesis using domain(π)M by (auto simp add:transitivity)
  qed
  also 
  have "... =  {x .. xc , qP. x  c  (M[G],  [x] @ env @ [c]   φ)  q  G}"
  proof

    show "...  {x .. xc , qP. x  c  (M[G],  [x] @ env @ [c]   φ)  q  G}"
      by auto
  next 
    (* Now we show the other inclusion:
      {x .. x∈c , ∃q∈P. x ∈ c ∧ (M[G],  [x, w, c] ⊨  φ) ∧ q ∈ G}
      ⊆
      {val(G,t)..t∈domain(π),∃q∈P.val(G,t)∈c∧(M[G], [val(G,t),w] ⊨ φ)∧q∈G}
    *)
    {
      fix x
      assume "x{x .. xc , qP. x  c  (M[G],  [x] @ env @ [c]   φ)  q  G}"
      then 
      have "qP. x  c  (M[G],  [x] @ env @ [c]   φ)  q  G"
        by simp
      with val(G,π) = c  
      have "qP. tdomain(π). val(G,t) =x  (M[G],  [val(G,t)] @ env @ [c]   φ)  q  G" 
        using Sep_and_Replace elem_of_val by auto
    }
    then 
    show " {x .. xc , qP. x  c  (M[G],  [x] @ env @ [c]   φ)  q  G}  ..."
      using SepReplace_iff by force
  qed
  also 
  have " ... = {xc. (M[G], [x] @ env @ [c]  φ)}"
    using GP G_nonempty by force
  finally 
  have val_m: "val(G,?m) = {xc. (M[G], [x] @ env @ [c]  φ)}" by simp
  have "val(G,?m)  val(G,?n)" 
  proof
    fix x
    assume "x  val(G,?m)"
    with val_m 
    have Eq4: "x  {xc. (M[G], [x] @ env @ [c]  φ)}" by simp
    with val(G,π) = c
    have "x  val(G,π)" by simp
    then 
    have "θ. qG. θ,qπ  val(G,θ) =x" 
      using elem_of_val_pair by auto
    then obtain θ q where
      "θ,qπ" "qG" "val(G,θ)=x" by auto
    from θ,qπ
    have "θM"
      using domain_trans[OF trans_M π_] by auto
    with πM nenv  _ env = _
    have "[val(G,θ), val(G,π)] @ env list(M[G])" 
      using GenExt_def by auto
    with  Eq4 val(G,θ)=x val(G,π) = c x  val(G,π) nth θM
    have Eq5: "M[G],  [val(G,θ)] @ env @[val(G,π)]  And(Member(0,1 #+ length(env)),φ)" 
      by auto
        (* Recall ?χ = And(Member(0,1 #+ length(env)),φ) *)
    with θM πM  Eq5 M_generic(G) φformula nenv  _ env = _ map_nenv 
      arity()  length([θ] @ nenv @ [π])
    have "(rG. M,  [r,P,leq,one,θ] @ nenv @[π]  forces())"
      using truth_lemma  
      by auto
    then obtain r where      (* I can't "obtain" this directly *)
      "rG" "M,  [r,P,leq,one,θ] @ nenv @ [π]  forces()" by auto
    with filter(G) and qG obtain p where
      "pG" "pq" "pr" 
      unfolding filter_def compat_in_def by force
    with rG  qG GP 
    have "pP" "rP" "qP" "pM"
      using  P_in_M  by (auto simp add:transitivity)
    with φformula θM πM  pr nenv  _ arity()  length([θ] @ nenv @ [π])
      M, [r,P,leq,one,θ] @ nenv @ [π]  forces() env_
    have "M,  [p,P,leq,one,θ] @ nenv @ [π]  forces()"
      using strengthening_lemma 
      by simp
    with pP φformula θM πM nenv  _ arity()  length([θ] @ nenv @ [π])
    have "F. M_generic(F)  p  F  
                 M[F],   map(val(F), [θ] @ nenv @[π])   "
      using definition_of_forcing
      by simp
    with pP θM  
    have Eq6: "θ'M. p'P.  θ,p = <θ',p'>  (F. M_generic(F)  p'  F  
                 M[F],   map(val(F), [θ'] @ nenv @ [π])   )" by auto
    from πM θ,qπ 
    have "θ,q  M" by (simp add:transitivity)
    from θ,qπ θM pP  pM 
    have "θ,pM" "θ,pdomain(π)×P" 
      using tuples_in_M by auto
    with θM Eq6 pP
    have "M, [θ,p] @ ?Pl1 @ [π] @ nenv  "
      using Equivalence  by auto
    with θ,pdomain(π)×P 
    have "θ,p?n" by simp
    with pG pP 
    have "val(G,θ)val(G,?n)" 
      using  val_of_elem[of θ p] by simp
    with val(G,θ)=x 
    show "xval(G,?n)" by simp
  qed (* proof of "val(G,?m) ⊆ val(G,?n)" *)
  with val_m first_incl 
  have "val(G,?n) = {xc. (M[G], [x] @ env @ [c]  φ)}" by auto
  also 
  have " ... = {xc. (M[G], [x] @ env  φ)}" 
  proof -
    {
      fix x
      assume "xc"
      moreover from assms 
      have "cM[G]"
        unfolding GenExt_def by auto
      moreover from this and xc 
      have "xM[G]"
        using transitivity_MG
        by simp
      ultimately 
      have "(M[G],  ([x] @ env) @[c]   φ)  (M[G],  [x] @ env   φ)" 
        using phi env  _ by (rule_tac arity_sats_iff, simp_all)   (* Enhance this *)
    }
    then show ?thesis by auto
  qed      
  finally 
  show "{xc. (M[G], [x] @ env  φ)} M[G]" 
    using ?nM GenExt_def by force
qed

theorem separation_in_MG:
  assumes 
    "φformula" and "arity(φ)  1 #+ length(env)" and "envlist(M[G])"
  shows  
    "separation(##M[G],λx. (M[G], [x] @ env  φ))"
proof -
  { 
    fix c
    assume "cM[G]" 
    moreover from env  _
    obtain nenv where  "nenvlist(M)" 
      "env = map(val(G),nenv)" "length(env) = length(nenv)"
      using GenExt_def map_val[of env] by auto
    moreover note φ  _ arity(φ)  _ env  _
    ultimately
    have Eq1: "{xc. (M[G], [x] @ env  φ)}  M[G]"
      using Collect_sats_in_MG  by auto
  }
  then 
  show ?thesis 
    using separation_iff rev_bexI unfolding is_Collect_def by force
qed

end (* context: G_generic *)

end