Theory WFrec

(*  Title:      ZF/Constructible/WFrec.thy
    Author:     Lawrence C Paulson, Cambridge University Computer Laboratory

section‹Relativized Well-Founded Recursion›

theory WFrec imports Wellorderings begin

subsection‹General Lemmas›

(*Many of these might be useful in WF.thy*)

lemma apply_recfun2:
    "is_recfun(r,a,H,f); x,i:f  i = H(x, restrict(f,r-``{x}))"
apply (frule apply_recfun) 
 apply (blast dest: is_recfun_type fun_is_rel) 
apply (simp add: function_apply_equality [OF _ is_recfun_imp_function])

text‹Expresses is_recfun› as a recursion equation›
lemma is_recfun_iff_equation:
           f  r -`` {a}  range(f) 
           (x  r-``{a}. f`x = H(x, restrict(f, r-``{x})))"  
apply (rule iffI) 
 apply (simp add: is_recfun_type apply_recfun Ball_def vimage_singleton_iff, 
apply (simp add: is_recfun_def) 
apply (rule fun_extension) 
  apply assumption
 apply (fast intro: lam_type, simp) 

lemma is_recfun_imp_in_r: "is_recfun(r,a,H,f); x,i  f  x, a  r"
by (blast dest: is_recfun_type fun_is_rel)

lemma trans_Int_eq:
      "trans(r); y,x  r  r -`` {x}  r -`` {y} = r -`` {y}"
by (blast intro: transD) 

lemma is_recfun_restrict_idem:
     "is_recfun(r,a,H,f)  restrict(f, r -`` {a}) = f"
apply (drule is_recfun_type)
apply (auto simp add: Pi_iff subset_Sigma_imp_relation restrict_idem)  

lemma is_recfun_cong_lemma:
  "is_recfun(r,a,H,f); r = r'; a = a'; f = f'; 
      x g. <x,a'>  r'; relation(g); domain(g)  r' -``{x} 
              H(x,g) = H'(x,g)
apply (simp add: is_recfun_def) 
apply (erule trans) 
apply (rule lam_cong) 
apply (simp_all add: vimage_singleton_iff Int_lower2)  

text‹For is_recfun› we need only pay attention to functions
      whose domains are initial segments of termr.›
lemma is_recfun_cong:
  "r = r'; a = a'; f = f'; 
      x g. <x,a'>  r'; relation(g); domain(g)  r' -``{x} 
              H(x,g) = H'(x,g)
    is_recfun(r,a,H,f)  is_recfun(r',a',H',f')"
apply (rule iffI)
txt‹Messy: fast and blast don't work for some reason›
apply (erule is_recfun_cong_lemma, auto) 
apply (erule is_recfun_cong_lemma)
apply (blast intro: sym)+

subsection‹Reworking of the Recursion Theory Within termM

lemma (in M_basic) is_recfun_separation':
    "f  r -`` {a}  range(f); g  r -`` {b}  range(g);
        M(r); M(f); M(g); M(a); M(b) 
      separation(M, λx. ¬ (x, a  r  x, b  r  f ` x = g ` x))"
apply (insert is_recfun_separation [of r f g a b]) 
apply (simp add: vimage_singleton_iff)

text‹Stated using termtrans(r) rather than
      termtransitive_rel(M,A,r) because the latter rewrites to
      the former anyway, by transitive_rel_abs›.
      As always, theorems should be expressed in simplified form.
      The last three M-premises are redundant because of termM(r), 
      but without them we'd have to undertake
      more work to set up the induction formula.›
lemma (in M_basic) is_recfun_equal [rule_format]: 
    "is_recfun(r,a,H,f);  is_recfun(r,b,H,g);  
       wellfounded(M,r);  trans(r);
       M(f); M(g); M(r); M(x); M(a); M(b) 
      x,a  r  x,b  r  f`x=g`x"
apply (frule_tac f=f in is_recfun_type) 
apply (frule_tac f=g in is_recfun_type) 
apply (simp add: is_recfun_def)
apply (erule_tac a=x in wellfounded_induct, assumption+)
txt‹Separation to justify the induction›
 apply (blast intro: is_recfun_separation') 
txt‹Now the inductive argument itself›
apply clarify 
apply (erule ssubst)+
apply (simp (no_asm_simp) add: vimage_singleton_iff restrict_def)
apply (rename_tac x1)
apply (rule_tac t="λz. H(x1,z)" in subst_context) 
apply (subgoal_tac "y  r-``{x1}. z. y,zf  y,zg")
 apply (blast intro: transD) 
apply (simp add: apply_iff) 
apply (blast intro: transD sym) 

lemma (in M_basic) is_recfun_cut: 
    "is_recfun(r,a,H,f);  is_recfun(r,b,H,g);  
       wellfounded(M,r); trans(r); 
       M(f); M(g); M(r); b,a  r   
       restrict(f, r-``{b}) = g"
apply (frule_tac f=f in is_recfun_type) 
apply (rule fun_extension) 
apply (blast intro: transD restrict_type2) 
apply (erule is_recfun_type, simp) 
apply (blast intro: is_recfun_equal transD dest: transM) 

lemma (in M_basic) is_recfun_functional:
     "is_recfun(r,a,H,f);  is_recfun(r,a,H,g);  
       wellfounded(M,r); trans(r); M(f); M(g); M(r)  f=g"
apply (rule fun_extension)
apply (erule is_recfun_type)+
apply (blast intro!: is_recfun_equal dest: transM) 

text‹Tells us that is_recfun› can (in principle) be relativized.›
lemma (in M_basic) is_recfun_relativize:
  "M(r); M(f); x[M]. g[M]. function(g)  M(H(x,g)) 
       (z[M]. z  f  
        (x[M]. x,a  r  z = <x, H(x, restrict(f, r-``{x}))>))"
apply (simp add: is_recfun_def lam_def)
apply (safe intro!: equalityI) 
   apply (drule equalityD1 [THEN subsetD], assumption) 
   apply (blast dest: pair_components_in_M) 
  apply (blast elim!: equalityE dest: pair_components_in_M)
 apply (frule transM, assumption) 
 apply simp  
 apply blast
apply (subgoal_tac "is_function(M,f)")
 txt‹We use termis_function rather than termfunction because
      the subgoal's easier to prove with relativized quantifiers!›
 prefer 2 apply (simp add: is_function_def) 
apply (frule pair_components_in_M, assumption) 
apply (simp add: is_recfun_imp_function function_restrictI) 

lemma (in M_basic) is_recfun_restrict:
     "wellfounded(M,r); trans(r); is_recfun(r,x,H,f); y,x  r; 
       M(r); M(f); 
       x[M]. g[M]. function(g)  M(H(x,g))
        is_recfun(r, y, H, restrict(f, r -`` {y}))"
apply (frule pair_components_in_M, assumption, clarify) 
apply (simp (no_asm_simp) add: is_recfun_relativize restrict_iff
apply safe
  apply (simp_all add: vimage_singleton_iff is_recfun_type [THEN apply_iff]) 
  apply (frule_tac x=xa in pair_components_in_M, assumption)
  apply (frule_tac x=xa in apply_recfun, blast intro: transD)  
  apply (simp add: is_recfun_type [THEN apply_iff] 
                   is_recfun_imp_function function_restrictI)
apply (blast intro: apply_recfun dest: transD)
lemma (in M_basic) restrict_Y_lemma:
   "wellfounded(M,r); trans(r); M(r);
       x[M]. g[M]. function(g)  M(H(x,g));  M(Y);
           b  Y 
           (x[M]. x,a1  r 
            (y[M]. b = x,y  (g[M]. is_recfun(r,x,H,g)  y = H(x,g))));
          x,a1  r; is_recfun(r,x,H,f); M(f)
        restrict(Y, r -`` {x}) = f"
apply (subgoal_tac "y  r-``{x}. z. y,z:Y  y,z:f") 
 apply (simp (no_asm_simp) add: restrict_def) 
 apply (thin_tac "rall(M,P)" for P)+  ― ‹essential for efficiency›
 apply (frule is_recfun_type [THEN fun_is_rel], blast)
apply (frule pair_components_in_M, assumption, clarify) 
apply (rule iffI)
 apply (frule_tac y="y,z" in transM, assumption)
 apply (clarsimp simp add: vimage_singleton_iff is_recfun_type [THEN apply_iff]
                           apply_recfun is_recfun_cut) 
txt‹Opposite inclusion: something in f, show in Y›
apply (frule_tac y="y,z" in transM, assumption)  
apply (simp add: vimage_singleton_iff) 
apply (rule conjI) 
 apply (blast dest: transD) 
apply (rule_tac x="restrict(f, r -`` {y})" in rexI) 
apply (simp_all add: is_recfun_restrict
                     apply_recfun is_recfun_type [THEN apply_iff]) 

text‹For typical applications of Replacement for recursive definitions›
lemma (in M_basic) univalent_is_recfun:
     "wellfounded(M,r); trans(r); M(r)
       univalent (M, A, λx p. 
              y[M]. p = x,y  (f[M]. is_recfun(r,x,H,f)  y = H(x,f)))"
apply (simp add: univalent_def) 
apply (blast dest: is_recfun_functional) 

text‹Proof of the inductive step for exists_is_recfun›, since
      we must prove two versions.›
lemma (in M_basic) exists_is_recfun_indstep:
    "y. y, a1  r  (f[M]. is_recfun(r, y, H, f)); 
       wellfounded(M,r); trans(r); M(r); M(a1);
       strong_replacement(M, λx z. 
              y[M]. g[M]. pair(M,x,y,z)  is_recfun(r,x,H,g)  y = H(x,g)); 
       x[M]. g[M]. function(g)  M(H(x,g))   
       f[M]. is_recfun(r,a1,H,f)"
apply (drule_tac A="r-``{a1}" in strong_replacementD)
  apply blast 
 txt‹Discharge the "univalent" obligation of Replacement›
 apply (simp add: univalent_is_recfun) 
txt‹Show that the constructed object satisfies is_recfun› 
apply clarify 
apply (rule_tac x=Y in rexI)  
txt‹Unfold only the top-level occurrence of termis_recfun
apply (simp (no_asm_simp) add: is_recfun_relativize [of concl: _ a1])
txt‹The big iff-formula defining termY is now redundant›
apply safe 
 apply (simp add: vimage_singleton_iff restrict_Y_lemma [of r H _ a1]) 
txt‹one more case›
apply (simp (no_asm_simp) add: Bex_def vimage_singleton_iff)
apply (drule_tac x1=x in spec [THEN mp], assumption, clarify) 
apply (rename_tac f) 
apply (rule_tac x=f in rexI) 
apply (simp_all add: restrict_Y_lemma [of r H])
txt‹FIXME: should not be needed!›
apply (subst restrict_Y_lemma [of r H])
apply (simp add: vimage_singleton_iff)+
apply blast+

text‹Relativized version, when we have the (currently weaker) premise
lemma (in M_basic) wellfounded_exists_is_recfun:
    "wellfounded(M,r);  trans(r);  
       separation(M, λx. ¬ (f[M]. is_recfun(r, x, H, f)));
       strong_replacement(M, λx z. 
          y[M]. g[M]. pair(M,x,y,z)  is_recfun(r,x,H,g)  y = H(x,g)); 
       M(r);  M(a);  
       x[M]. g[M]. function(g)  M(H(x,g))   
       f[M]. is_recfun(r,a,H,f)"
apply (rule wellfounded_induct, assumption+, clarify)
apply (rule exists_is_recfun_indstep, assumption+)

lemma (in M_basic) wf_exists_is_recfun [rule_format]:
    "wf(r);  trans(r);  M(r);  
       strong_replacement(M, λx z. 
         y[M]. g[M]. pair(M,x,y,z)  is_recfun(r,x,H,g)  y = H(x,g)); 
       x[M]. g[M]. function(g)  M(H(x,g))   
       M(a)  (f[M]. is_recfun(r,a,H,f))"
apply (rule wf_induct, assumption+)
apply (frule wf_imp_relativized)
apply (intro impI)
apply (rule exists_is_recfun_indstep) 
      apply (blast dest: transM del: rev_rallE, assumption+)

subsection‹Relativization of the ZF Predicate termis_recfun

  M_is_recfun :: "[io, [i,i,i]o, i, i, i]  o" where
     z[M]. z  f  
            (x[M]. y[M]. xa[M]. sx[M]. r_sx[M]. f_r_sx[M]. 
               pair(M,x,y,z)  pair(M,x,a,xa)  upair(M,x,x,sx) 
               pre_image(M,r,sx,r_sx)  restriction(M,f,r_sx,f_r_sx) 
               xa  r  MH(x, f_r_sx, y))"

  is_wfrec :: "[io, [i,i,i]o, i, i, i]  o" where
      f[M]. M_is_recfun(M,MH,r,a,f)  MH(a,f,z)"

  wfrec_replacement :: "[io, [i,i,i]o, i]  o" where
             λx z. y[M]. pair(M,x,y,z)  is_wfrec(M,MH,r,x,y))"

lemma (in M_basic) is_recfun_abs:
     "x[M]. g[M]. function(g)  M(H(x,g));  M(r); M(a); M(f); 
       M_is_recfun(M,MH,r,a,f)  is_recfun(r,a,H,f)"
apply (simp add: M_is_recfun_def relation2_def is_recfun_relativize)
apply (rule rall_cong)
apply (blast dest: transM)

lemma M_is_recfun_cong [cong]:
     "r = r'; a = a'; f = f'; 
       x g y. M(x); M(g); M(y)  MH(x,g,y)  MH'(x,g,y)
       M_is_recfun(M,MH,r,a,f)  M_is_recfun(M,MH',r',a',f')"
by (simp add: M_is_recfun_def) 

lemma (in M_basic) is_wfrec_abs:
     "x[M]. g[M]. function(g)  M(H(x,g)); 
         relation2(M,MH,H);  M(r); M(a); M(z)
          (g[M]. is_recfun(r,a,H,g)  z = H(a,g))"
by (simp add: is_wfrec_def relation2_def is_recfun_abs)

text‹Relating termwfrec_replacement to native constructs›
lemma (in M_basic) wfrec_replacement':
     x[M]. g[M]. function(g)  M(H(x,g)); 
     relation2(M,MH,H);  M(r) 
    strong_replacement(M, λx z. y[M]. 
                pair(M,x,y,z)  (g[M]. is_recfun(r,x,H,g)  y = H(x,g)))"
by (simp add: wfrec_replacement_def is_wfrec_abs) 

lemma wfrec_replacement_cong [cong]:
     "x y z. M(x); M(y); M(z)  MH(x,y,z)  MH'(x,y,z);
       wfrec_replacement(M, λx y. MH(x,y), r)  
          wfrec_replacement(M, λx y. MH'(x,y), r')" 
by (simp add: is_wfrec_def wfrec_replacement_def)