Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Archive-of-Formal-Proofs/thys/MiniSail/   (Sammlung formaler Beweise Version 2026-5©)  Datei vom 31.4.2026 mit Größe 81 kB image not shown  

Quellcode-Bibliothek BTVSubst.thy

  Sprache: Isabelle
 

(*<*)
theory BTVSubst
  imports Syntax
begin
  (*>*)
chapter Basic Type Variable Substitution

section Class

class has_subst_b = fs +
  fixes subst_b :: "'a::fs ==> bv ==> b ==> 'a::fs" (_[_::=_]b [1000,50,501000)

assumes fresh_subst_if:  "j (t[i::=x]b ) (atom i t j t) (j x (j t j = atom i))" 
  and    forget_subst[simp]:  "atom a tm ==> tm[a::=x]b = tm"
  and    subst_id[simp]:      "tm[a::=(B_var a)]b = tm"
  and    eqvt[simp,eqvt]:          "(p::perm) (subst_b t1 x1 v ) = (subst_b (p t1) (p x1) (p v) )"
  and    flip_subst[simp]:    "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
  and    flip_subst_subst[simp]: "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
begin

lemmas flip_subst_b = flip_subst_subst

lemma subst_b_simple_commute:
  fixes x::bv
  assumes "atom x c" 
  shows "(c[z::=B_var x]b)[x::=b]b = c[z::=b]b" 
proof - 
  have "(c[z::=B_var x]b)[x::=b]b = (( x z) c)[x::=b]b" using flip_subst assms by simp
  thus ?thesis using flip_subst_subst assms by simp
qed

lemma subst_b_flip_eq_one:
  fixes z1::bv and z2::bv and x1::bv and x2::bv  
  assumes "[[atom z1]]lst. c1 = [[atom z2]]lst. c2" 
    and "atom x1 (z1,z2,c1,c2)"
  shows "(c1[z1::=B_var x1]b) = (c2[z2::=B_var x1]b)"
proof -  
  have "(c1[z1::=B_var x1]b) = (x1 z1) c1" using assms flip_subst by auto
  moreover have  "(c2[z2::=B_var x1]b) = (x1 z2) c2" using assms flip_subst by auto
  ultimately show ?thesis using Abs1_eq_iff_all(3)[of z1 c1 z2 c2 z1]  assms 
    by (metis Abs1_eq_iff_fresh(3) flip_commute)
qed

lemma subst_b_flip_eq_two:
  fixes z1::bv and z2::bv and x1::bv and x2::bv  
  assumes "[[atom z1]]lst. c1 = [[atom z2]]lst. c2" 
  shows "(c1[z1::=b]b) = (c2[z2::=b]b)"
proof -
  obtain x::bv where *:"atom x (z1,z2,c1,c2)" using obtain_fresh by metis
  hence "(c1[z1::=B_var x]b) = (c2[z2::=B_var x]b)" using subst_b_flip_eq_one[OF assms, of x] by metis
  hence "(c1[z1::=B_var x]b)[x::=b]b = (c2[z2::=B_var x]b)[x::=b]b" by auto
  thus ?thesis using subst_b_simple_commute * fresh_prod4 by metis
qed

lemma subst_b_fresh_x:
  fixes tm::"'a::fs" and x::x
  shows "atom x tm = atom x tm[bv::=b']b"
  using fresh_subst_if[of "atom x" tm bv b'] using x_fresh_b by auto

lemma subst_b_x_flip[simp]:
  fixes x'::x and x::x and bv::bv 
  shows "((x' x) tm)[bv::=b']b = (x' x) (tm[bv::=b']b)"
proof - 
  have "(x' x) bv = bv" using pure_supp flip_fresh_fresh by force
  moreover have "(x' x) b' = b'" using x_fresh_b flip_fresh_fresh by auto
  ultimately show ?thesis using eqvt by simp
qed

end

section Base Type

nominal_function subst_bb :: "b ==> bv ==> b ==> b" where
  "subst_bb (B_var bv2) bv1 b = (if bv1 = bv2 then b else (B_var bv2))"
"subst_bb B_int bv1 b = B_int"
"subst_bb B_bool bv1 b = B_bool"
"subst_bb (B_id s) bv1 b = B_id s "
"subst_bb (B_pair b1 b2) bv1 b = B_pair (subst_bb b1 bv1 b) (subst_bb b2 bv1 b)"
"subst_bb B_unit bv1 b = B_unit "
"subst_bb B_bitvec bv1 b = B_bitvec "
"subst_bb (B_app s b2) bv1 b = B_app s (subst_bb b2 bv1 b)"
                      apply (simp add: eqvt_def subst_bb_graph_aux_def )
                      apply (simp add: eqvt_def subst_bb_graph_aux_def )
  by (auto,meson b.strong_exhaust)
nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_bb_abbrev :: "b ==> bv ==> b ==> b" (_[_::=_]bb [1000,50,501000)
  where 
    "b[bv::=b']bb subst_bb b bv b' " 

instantiation b :: has_subst_b
begin
definition "subst_b = subst_bb"

instance proof
  fix j::atom and i::bv and  x::b and t::b
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
  proof (induct t rule: b.induct)
    case (B_id x)
    then show ?case using subst_bb.simps fresh_def pure_fresh subst_b_b_def by auto
  next
    case (B_var x)
    then show ?case using subst_bb.simps fresh_def pure_fresh subst_b_b_def by auto
  next
    case (B_app x1 x2)
    then show ?case using subst_bb.simps fresh_def pure_fresh subst_b_b_def by auto
  qed(auto simp add: subst_bb.simps fresh_def pure_fresh subst_b_b_def)+

  fix a::bv and tm::b and x::b
  show "atom a tm ==> tm[a::=x]b = tm"
    by (induct tm rule: b.induct, auto simp add: fresh_at_base subst_bb.simps subst_b_b_def)

  fix a::bv and tm::b
  show "subst_b tm a (B_var a) = tm" using subst_bb.simps  subst_b_b_def 
    by (induct tm rule: b.induct, auto simp add: fresh_at_base subst_bb.simps subst_b_b_def)

  fix p::perm and x1::bv and v::b and t1::b
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" 
    by (induct tm rule: b.induct, auto simp add: fresh_at_base subst_bb.simps subst_b_b_def)

  fix  bv::bv and c::b and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    by (induct c rule: b.induct,  (auto simp add: fresh_at_base subst_bb.simps subst_b_b_def permute_pure pure_supp )+)

  fix bv::bv and c::b and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
    by (induct c rule: b.induct,  (auto simp add: fresh_at_base subst_bb.simps subst_b_b_def permute_pure pure_supp )+)
qed
end

lemma subst_bb_inject:
  assumes "b1 = b2[bv::=b]bb" and "b2 B_var bv" 
  shows 
    "b1 = B_int ==> b2 = B_int" and 
    "b1 = B_bool ==> b2 = B_bool" and 
    "b1 = B_unit ==> b2 = B_unit" and 
    "b1 = B_bitvec ==> b2 = B_bitvec" and 
    "b1 = B_pair b11 b12 ==> (b11' b12' . b11 = b11'[bv::=b]bb b12 = b12'[bv::=b]bb b2 = B_pair b11' b12')" and
    "b1 = B_var bv' ==> b2 = B_var bv'" and
    "b1 = B_id tyid ==> b2 = B_id tyid" and
    "b1 = B_app tyid b11 ==> (b11'. b11= b11'[bv::=b]bb b2 = B_app tyid b11')"
  using assms by(nominal_induct b2 rule:b.strong_induct,auto+)

lemma flip_b_subst4:
  fixes b1::b and bv1::bv and c::bv and b::b
  assumes "atom c (b1,bv1)" 
  shows "b1[bv1::=b]bb = ((bv1 c) b1)[c ::= b]bb" 
  using assms proof(nominal_induct b1 rule: b.strong_induct)
  case B_int
  then show ?case using subst_bb.simps b.perm_simps by auto
next
  case B_bool
  then show ?case using subst_bb.simps b.perm_simps by auto
next
  case (B_id x)
  hence "atom bv1 x atom c x" using fresh_def  pure_supp by auto
  hence "((bv1 c) B_id x) = B_id x" using fresh_Pair b.fresh(3) flip_fresh_fresh b.perm_simps fresh_def pure_supp by metis
  then show ?case using subst_bb.simps by simp
next
  case (B_pair x1 x2)
  hence "x1[bv1::=b]bb = ((bv1 c) x1)[c::=b]bb" using  b.perm_simps(4) b.fresh(4) fresh_Pair  by metis
  moreover have  "x2[bv1::=b]bb = ((bv1 c) x2)[c::=b]bb" using  b.perm_simps(4) b.fresh(4) fresh_Pair B_pair by metis
  ultimately  show ?case using subst_bb.simps(5) b.perm_simps(4) b.fresh(4) fresh_Pair by auto
next
  case B_unit
  then show ?case using subst_bb.simps b.perm_simps by auto
next
  case B_bitvec
  then show ?case using subst_bb.simps b.perm_simps by auto
next
  case (B_var x)
  then show ?case proof(cases "x=bv1")
    case True
    then show ?thesis using B_var subst_bb.simps b.perm_simps by simp
  next
    case False
    moreover have "xc" using B_var b.fresh fresh_def supp_at_base fresh_Pair by fastforce
    ultimately show ?thesis using B_var subst_bb.simps(1) b.perm_simps(7by simp
  qed
next
  case (B_app x1 x2)
  hence "x2[bv1::=b]bb = ((bv1 c) x2)[c::=b]bb" using  b.perm_simps b.fresh fresh_Pair  by metis 
  thus ?case using subst_bb.simps b.perm_simps b.fresh fresh_Pair B_app 
    by (simp add: permute_pure)
qed

lemma subst_bb_flip_sym:
  fixes b1::b and b2::b
  assumes "atom c b" and "atom c (bv1,bv2, b1, b2)" and "(bv1 c) b1 = (bv2 c) b2" 
  shows "b1[bv1::=b]bb = b2[bv2::=b]bb"
  using assms  flip_b_subst4[of c b1 bv1 b]   flip_b_subst4[of c b2 bv2 b] fresh_prod4 fresh_Pair by simp

section Value

nominal_function subst_vb :: "v ==> bv ==> b ==> v" where
  "subst_vb (V_lit l) x v = V_lit l"
"subst_vb (V_var y) x v = V_var y"
"subst_vb (V_cons tyid c v') x v = V_cons tyid c (subst_vb v' x v)"
"subst_vb (V_consp tyid c b v') x v = V_consp tyid c (subst_bb b x v) (subst_vb v' x v)"
"subst_vb (V_pair v1 v2) x v = V_pair (subst_vb v1 x v ) (subst_vb v2 x v )"
                   apply (simp add: eqvt_def subst_vb_graph_aux_def)
                  apply auto
  using v.strong_exhaust by meson
nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_vb_abbrev :: "v ==> bv ==> b ==> v" (_[_::=_]vb [1000,50,50500)
  where 
    "e[bv::=b]vb subst_vb e bv b" 

instantiation v :: has_subst_b
begin
definition "subst_b = subst_vb"

instance proof
  fix j::atom and i::bv and  x::b and t::v
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
  proof (induct t rule: v.induct)
    case (V_lit l)
    have "j subst_b (V_lit l) i x = j (V_lit l)"  using subst_vb.simps fresh_def pure_fresh 
        subst_b_v_def v.supp  v.fresh has_subst_b_class.fresh_subst_if subst_b_b_def subst_b_v_def by auto
    also have "... = True" using fresh_at_base v.fresh l.fresh supp_l_empty fresh_def by metis      
    moreover have "(atom i (V_lit l) j (V_lit l) j x (j (V_lit l) j = atom i)) = True" using fresh_at_base v.fresh l.fresh supp_l_empty fresh_def by metis
    ultimately show ?case by simp
  next
    case (V_var y)
    then show ?case using  subst_b_v_def subst_vb.simps pure_fresh by force   
  next
    case (V_pair x1a x2a)
    then show ?case using subst_b_v_def subst_vb.simps by auto  
  next
    case (V_cons x1a x2a x3)       
    then show ?case using V_cons subst_b_v_def subst_vb.simps pure_fresh by force
  next
    case (V_consp x1a x2a x3 x4)
    then show ?case using  subst_b_v_def subst_vb.simps pure_fresh  has_subst_b_class.fresh_subst_if subst_b_b_def subst_b_v_def by fastforce
  qed

  fix a::bv and tm::v and x::b
  show "atom a tm ==> subst_b tm a x = tm"
    apply(induct tm rule: v.induct)
        apply(auto simp add: fresh_at_base subst_vb.simps subst_b_v_def)
    using has_subst_b_class.fresh_subst_if  subst_b_b_def e.fresh 
    using has_subst_b_class.forget_subst by fastforce

  fix a::bv and tm::v
  show "subst_b tm a (B_var a) = tm" using subst_bb.simps  subst_b_b_def 
    apply (induct tm rule: v.induct)
        apply(auto simp add: fresh_at_base subst_vb.simps subst_b_v_def)
    using has_subst_b_class.fresh_subst_if  subst_b_b_def e.fresh 
    using has_subst_b_class.subst_id by metis

  fix p::perm and x1::bv and v::b and t1::v
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" 
    apply(induct tm rule: v.induct)
        apply(auto simp add: fresh_at_base subst_bb.simps subst_b_b_def )
    using has_subst_b_class.eqvt  subst_b_b_def e.fresh 
    using has_subst_b_class.eqvt 
    by (simp add: subst_b_v_def)+

  fix  bv::bv and c::v and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    apply (induct c rule: v.induct,  (auto simp add: fresh_at_base  subst_vb.simps subst_b_v_def permute_pure pure_supp )+)
     apply (metis flip_fresh_fresh flip_l_eq permute_flip_cancel2)
    using  fresh_at_base flip_fresh_fresh[of bv  x z] 
    apply (simp add: flip_fresh_fresh)
    using subst_b_b_def by argo

  fix bv::bv and c::v and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
    apply (induct c rule: v.induct,  (auto simp add: fresh_at_base  subst_vb.simps subst_b_v_def permute_pure pure_supp )+)
     apply (metis flip_fresh_fresh flip_l_eq permute_flip_cancel2)
    using  fresh_at_base flip_fresh_fresh[of bv  x z] 
    apply (simp add: flip_fresh_fresh)
    using     subst_b_b_def  flip_subst_subst by fastforce

qed
end

section Constraints Expressions

nominal_function subst_ceb :: "ce ==> bv ==> b ==> ce" where
  "subst_ceb ( (CE_val v') ) bv b = ( CE_val (subst_vb v' bv b) )"
"subst_ceb ( (CE_op opp v1 v2) ) bv b = ( (CE_op opp (subst_ceb v1 bv b)(subst_ceb v2 bv b)) )"
"subst_ceb ( (CE_fst v')) bv b = CE_fst (subst_ceb v' bv b)"
"subst_ceb ( (CE_snd v')) bv b = CE_snd (subst_ceb v' bv b)"
"subst_ceb ( (CE_len v')) bv b = CE_len (subst_ceb v' bv b)"
"subst_ceb ( CE_concat v1 v2) bv b = CE_concat (subst_ceb v1 bv b) (subst_ceb v2 bv b)"
                      apply (simp add: eqvt_def subst_ceb_graph_aux_def)
                      apply auto
  by (meson ce.strong_exhaust)
nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_ceb_abbrev :: "ce ==> bv ==> b ==> ce" (_[_::=_]ceb [1000,50,50500)
  where 
    "ce[bv::=b]ceb subst_ceb ce bv b" 

instantiation ce :: has_subst_b
begin
definition "subst_b = subst_ceb"

instance proof
  fix j::atom and i::bv and  x::b and t::ce
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
  proof (induct t rule: ce.induct)
    case (CE_val v)
    then show ?case using subst_ceb.simps fresh_def pure_fresh subst_b_ce_def ce.supp v.supp  ce.fresh has_subst_b_class.fresh_subst_if subst_b_b_def subst_b_v_def
      by metis
  next
    case (CE_op opp v1 v2)    

    have "(j v1[i::=x]ceb j v2[i::=x]ceb) = ((atom i v1 atom i v2) j v1 j v2 j x (j v1 j v2 j = atom i))"
      using has_subst_b_class.fresh_subst_if subst_b_v_def 
      using CE_op.hyps(1) CE_op.hyps(2) subst_b_ce_def by auto

    thus ?case  unfolding subst_ceb.simps subst_b_ce_def ce.fresh 
      using fresh_def pure_fresh opp.fresh subst_b_v_def  opp.exhaust fresh_e_opp_all
      by (metis (full_types))      
  next
    case (CE_concat x1a x2)
    then show ?case  using subst_ceb.simps  subst_b_ce_def e.supp v.supp  has_subst_b_class.fresh_subst_if subst_b_v_def  ce.fresh by force
  next
    case (CE_fst x)
    then show ?case using subst_ceb.simps  subst_b_ce_def e.supp v.supp  has_subst_b_class.fresh_subst_if subst_b_v_def  ce.fresh by metis

  next
    case (CE_snd x)
    then show ?case using subst_ceb.simps  subst_b_ce_def e.supp v.supp  has_subst_b_class.fresh_subst_if subst_b_v_def  ce.fresh by metis
  next
    case (CE_len x)
    then show ?case using subst_ceb.simps  subst_b_ce_def e.supp v.supp  has_subst_b_class.fresh_subst_if subst_b_v_def  ce.fresh by metis
  qed

  fix a::bv and tm::ce and x::b
  show "atom a tm ==> subst_b tm a x = tm"
    apply(induct tm rule: ce.induct)
         apply( auto simp add: fresh_at_base subst_ceb.simps subst_b_ce_def)
    using has_subst_b_class.fresh_subst_if  subst_b_b_def e.fresh 
    using has_subst_b_class.forget_subst subst_b_v_def apply metis+
    done

  fix a::bv and tm::ce
  show "subst_b tm a (B_var a) = tm" using subst_bb.simps  subst_b_b_def 
    apply (induct tm rule: ce.induct)
         apply(auto simp add: fresh_at_base subst_ceb.simps subst_b_ce_def)
    using has_subst_b_class.fresh_subst_if  subst_b_b_def e.fresh 
    using has_subst_b_class.subst_id subst_b_v_def apply metis+
    done

  fix p::perm and x1::bv and v::b and t1::ce
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" 
    apply(induct tm rule: ce.induct)
         apply( auto simp add: fresh_at_base subst_bb.simps subst_b_b_def )
    using has_subst_b_class.eqvt  subst_b_b_def ce.fresh 
    using has_subst_b_class.eqvt 
    by (simp add: subst_b_ce_def)+

  fix  bv::bv and c::ce and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    apply (induct c rule: ce.induct,  (auto simp add: fresh_at_base  subst_ceb.simps subst_b_ce_def permute_pure pure_supp )+)
    using  flip_fresh_fresh flip_l_eq permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_v_def apply metis
    using  flip_fresh_fresh flip_l_eq permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_v_def 
    by (simp add: flip_fresh_fresh fresh_opp_all)  

  fix bv::bv and c::ce and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
  proof (induct c rule: ce.induct)
    case (CE_val x)
    then show ?case using flip_subst_subst subst_b_v_def subst_ceb.simps  using subst_b_ce_deby fastforce
  next
    case (CE_op x1a x2 x3)
    then show ?case unfolding subst_ceb.simps subst_b_ce_def ce.perm_simps using flip_subst_subst subst_b_v_def  opp.perm_simps opp.strong_exhaust 
      by (metis (full_types) ce.fresh(2))
  next
    case (CE_concat x1a x2)
    then show ?case using flip_subst_subst subst_b_v_def subst_ceb.simps  using subst_b_ce_deby fastforce
  next
    case (CE_fst x)
    then show ?case using flip_subst_subst subst_b_v_def subst_ceb.simps  using subst_b_ce_deby fastforce
  next
    case (CE_snd x)
    then show ?case using flip_subst_subst subst_b_v_def subst_ceb.simps  using subst_b_ce_deby fastforce
  next
    case (CE_len x)
    then show ?case using flip_subst_subst subst_b_v_def subst_ceb.simps  using subst_b_ce_deby fastforce
  qed
qed
end

section Constraints

nominal_function subst_cb :: "c ==> bv ==> b ==> c" where
  "subst_cb (C_true) x v = C_true"
|  "subst_cb (C_false) x v = C_false"
|  "subst_cb (C_conj c1 c2) x v = C_conj (subst_cb c1 x v ) (subst_cb c2 x v )"
|  "subst_cb (C_disj c1 c2) x v = C_disj (subst_cb c1 x v ) (subst_cb c2 x v )"
|  "subst_cb (C_imp c1 c2) x v = C_imp (subst_cb c1 x v ) (subst_cb c2 x v )"
|  "subst_cb (C_eq e1 e2) x v = C_eq (subst_ceb e1 x v ) (subst_ceb e2 x v )"
|  "subst_cb (C_not c) x v = C_not (subst_cb c x v )"
                      apply (simp add: eqvt_def subst_cb_graph_aux_def)
                      apply auto 
  using c.strong_exhaust apply metis
  done
nominal_termination (eqvt)  by lexicographic_order

abbreviation 
  subst_cb_abbrev :: "c ==> bv ==> b ==> c" (_[_::=_]cb [1000,50,50500)
  where 
    "c[bv::=b]cb subst_cb c bv b" 

instantiation c :: has_subst_b
begin
definition "subst_b = subst_cb"

instance proof
  fix j::atom and i::bv and  x::b and t::c
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
    by (induct t rule: c.induct, unfold subst_cb.simps subst_b_c_def c.fresh,
        (metis has_subst_b_class.fresh_subst_if subst_b_ce_def c.fresh)+
        )

  fix a::bv and tm::c and x::b
  show "atom a tm ==> subst_b tm a x = tm"
    by(induct tm rule: c.induct, unfold subst_cb.simps subst_b_c_def c.fresh,
        (metis has_subst_b_class.forget_subst subst_b_ce_def)+)

  fix a::bv and tm::c
  show "subst_b tm a (B_var a) = tm" using subst_bb.simps  subst_b_c_def 
    by(induct tm rule: c.induct, unfold subst_cb.simps subst_b_c_def c.fresh,
        (metis has_subst_b_class.subst_id subst_b_ce_def)+)

  fix p::perm and x1::bv and v::b and t1::c
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" 
    apply(induct tm rule: c.induct,unfold subst_cb.simps subst_b_c_def c.fresh)
    by( auto simp add: fresh_at_base subst_bb.simps subst_b_b_def )

  fix  bv::bv and c::c and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    apply (induct c rule: c.induct,  (auto simp add: fresh_at_base  subst_cb.simps subst_b_c_def permute_pure pure_supp )+)
    using  flip_fresh_fresh flip_l_eq permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_ce_def apply metis
    using  flip_fresh_fresh flip_l_eq permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_ce_def 
    apply (metis opp.perm_simps(2) opp.strong_exhaust)+
    done

  fix bv::bv and c::c and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
    apply (induct c rule: c.induct,  (auto simp add: fresh_at_base  subst_cb.simps subst_b_c_def permute_pure pure_supp )+)
    using flip_fresh_fresh flip_l_eq permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_ce_def 
    using flip_subst_subst apply fastforce
    using  flip_fresh_fresh flip_l_eq permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_ce_def 
      opp.perm_simps(2) opp.strong_exhaust 
  proof -
    fix x1a :: ce and x2 :: ce
    assume a1: "atom bv x2"
    then have "((bv z) x2)[bv::=v]b = x2[z::=v]b"
      by (metis flip_subst_subst) (* 0.0 ms *)
    then show "x2[z::=B_var bv]b[bv::=v]ceb = x2[z::=v]ceb"
      using a1 by (simp add: subst_b_ce_def) (* 0.0 ms *)
  qed

qed
end

section Types

nominal_function subst_tb :: ==> bv ==> b ==> τ" where
  "subst_tb ({ z : b2 | c }) bv1 b1 = { z : b2[bv1::=b1]bb | c[bv1::=b1]cb }"
proof(goal_cases)
  case 1
  then show ?case using eqvt_def subst_tb_graph_aux_def by force
next
  case (2 x y)
  then show ?case by auto
next
  case (3 P x)
  then show ?case using eqvt_def subst_tb_graph_aux_def τ.strong_exhaust 
    by (metis b_of.cases prod_cases3)
next
  case (4 z' b2' c' bv1' b1' z b2 c bv1 b1)
  show ?case unfolding τ.eq_iff proof
    have *:"[[atom z']]lst. c' = [[atom z]]lst. c" using  τ.eq_iff 4 by auto
    show "[[atom z']]lst. c'[bv1'::=b1']cb = [[atom z]]lst. c[bv1::=b1]cb" 
    proof(subst Abs1_eq_iff_all(3),rule,rule,rule)
      fix ca::x
      assume "atom ca z" and 1:"atom ca (z', z, c'[bv1'::=b1']cb, c[bv1::=b1]cb)" 
      hence 2:"atom ca (c',c)" using fresh_subst_if subst_b_c_def fresh_Pair fresh_prod4 fresh_at_base subst_b_fresh_x by metis
      hence "(z' ca) c' = (z ca) c"  using 1 2 * Abs1_eq_iff_all(3by auto
      hence "((z' ca) c')[bv1'::=b1']cb = ((z ca) c)[bv1'::=b1']cb" by auto      
      hence "(z' ca) c'[(z' ca) bv1'::=(z' ca) b1']cb = (z ca) c[(z ca) bv1'::=(z ca) b1']cb" by auto  
      thus "(z' ca) c'[bv1'::=b1']cb = (z ca) c[bv1::=b1]cb" using  4  flip_x_b_cancel by simp
    qed
    show "b2'[bv1'::=b1']bb = b2[bv1::=b1]bb" using 4 by simp
  qed
qed

nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_tb_abbrev :: ==> bv ==> b ==> τ" (_[_::=_]\τb [1000,50,501000)
  where 
    "t[bv::=b']\<tau>b subst_tb t bv b' " 

instantiation τ :: has_subst_b
begin
definition "subst_b = subst_tb"

instance proof
  fix j::atom and i::bv and  x::b and t::τ
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
  proof (nominal_induct t avoiding: i x j rule: τ.strong_induct)
    case (T_refined_type z b c)
    then show ?case
      unfolding subst_b_τ_def  subst_tb.simps τ.fresh
      using fresh_subst_if[of j b i x ] subst_b_b_def subst_b_c_def
      by (metis has_subst_b_class.fresh_subst_if list.distinct(1) list.set_cases not_self_fresh set_ConsD)
  qed

  fix a::bv and tm::τ and x::b
  show "atom a tm ==> subst_b tm a x = tm"
  proof (nominal_induct tm avoiding: a x rule: τ.strong_induct)
    case (T_refined_type xx bb cc )
    moreover hence "atom a bb atom a cc" using τ.fresh by auto
    ultimately show   ?case  
      unfolding  subst_b_τ_def subst_tb.simps 
      using forget_subst subst_b_b_def subst_b_c_def forget_subst τ.fresh by metis
  qed

  fix a::bv and tm::τ
  show "subst_b tm a (B_var a) = tm" 
  proof (nominal_induct tm rule: τ.strong_induct)
    case (T_refined_type xx bb cc)
    thus  ?case  
      unfolding  subst_b_τ_def subst_tb.simps 
      using subst_id subst_b_b_def subst_b_c_def by metis
  qed

  fix p::perm and x1::bv and v::b and t1::τ
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v) " 
    by (induct tm rule: τ.induct, auto simp add: fresh_at_base subst_tb.simps subst_b_τ_def subst_bb.simps subst_b_b_def)

  fix  bv::bv and c::τ and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    apply (induct c rule: τ.induct,  (auto simp add: fresh_at_base  subst_ceb.simps subst_b_ce_def permute_pure pure_supp )+)
    using  flip_fresh_fresh permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_c_def  subst_b_b_def 
    by (simp add: flip_fresh_fresh subst_b_τ_def)

  fix bv::bv and c::τ and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
  proof (induct c rule: τ.induct)
    case (T_refined_type x1a x2a x3a)
    hence "atom bv x2a atom bv x3a atom bv x1a" using fresh_at_base τ.fresh by simp
    then show ?case 
      unfolding subst_tb.simps subst_b_τ_def τ.perm_simps 
      using fresh_at_base flip_fresh_fresh[of bv x1a z] flip_subst_subst subst_b_b_def  subst_b_c_def T_refined_type 
    proof -
      have "atom z x1a"
        by (metis b.fresh(7) fresh_at_base(2) x_fresh_b) (* 0.0 ms *)
      then show "{ (bv z) x1a : ((bv z) x2a)[bv::=v]bb | ((bv z) x3a)[bv::=v]cb } = { x1a : x2a[z::=v]bb | x3a[z::=v]cb }"
        by (metis [atom bv x1a; atom z x1a] ==> (bv z) x1a = x1a atom bv x2a atom bv x3a atom bv x1a flip_subst_subst subst_b_b_def subst_b_c_def) (* 78 ms *)
    qed 
  qed

qed
end

lemma subst_bb_commute [simp]:
  "atom j A ==> (subst_bb (subst_bb A i t ) j u ) = subst_bb A i (subst_bb t j u) "
  by (nominal_induct A avoiding: i j t u rule: b.strong_induct) (auto simp: fresh_at_base)

lemma subst_vb_commute [simp]:
  "atom j A ==> (subst_vb (subst_vb A i t )) j u = subst_vb A i (subst_bb t j u ) "
  by (nominal_induct A avoiding: i j t u rule: v.strong_induct) (auto simp: fresh_at_base)

lemma subst_ceb_commute [simp]:
  "atom j A ==> (subst_ceb (subst_ceb A i t )) j u = subst_ceb A i (subst_bb t j u ) "
  by (nominal_induct A avoiding: i j t u rule: ce.strong_induct) (auto simp: fresh_at_base)

lemma subst_cb_commute [simp]:
  "atom j A ==> (subst_cb (subst_cb A i t )) j u = subst_cb A i (subst_bb t j u ) "
  by (nominal_induct A avoiding: i j t u rule: c.strong_induct) (auto simp: fresh_at_base)

lemma subst_tb_commute [simp]:
  "atom j A ==> (subst_tb (subst_tb A i t )) j u = subst_tb A i (subst_bb t j u ) "
proof (nominal_induct A avoiding: i j t u rule: τ.strong_induct)
  case (T_refined_type z b c)
  then show ?case using subst_tb.simps subst_bb_commute subst_cb_commute by simp
qed

section Expressions

nominal_function subst_eb :: "e ==> bv ==> b ==> e" where
  "subst_eb ( (AE_val v')) bv b = ( AE_val (subst_vb v' bv b))"
"subst_eb ( (AE_app f v') ) bv b = ( (AE_app f (subst_vb v' bv b)) )"                
"subst_eb ( (AE_appP f b' v') ) bv b = ( (AE_appP f (b'[bv::=b]bb) (subst_vb v' bv b)))"   
"subst_eb ( (AE_op opp v1 v2) ) bv b = ( (AE_op opp (subst_vb v1 bv b) (subst_vb v2 bv b)) )"
"subst_eb ( (AE_fst v')) bv b = AE_fst (subst_vb v' bv b)"
"subst_eb ( (AE_snd v')) bv b = AE_snd (subst_vb v' bv b)"
"subst_eb ( (AE_mvar u)) bv b = AE_mvar u"
"subst_eb ( (AE_len v')) bv b = AE_len (subst_vb v' bv b)"
"subst_eb ( AE_concat v1 v2) bv b = AE_concat (subst_vb v1 bv b) (subst_vb v2 bv b)"
"subst_eb ( AE_split v1 v2) bv b = AE_split (subst_vb v1 bv b) (subst_vb v2 bv b)"
                      apply (simp add: eqvt_def subst_eb_graph_aux_def)
                      apply auto
  by (meson e.strong_exhaust)
nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_eb_abbrev :: "e ==> bv ==> b ==> e" (_[_::=_]eb [1000,50,50500)
  where 
    "e[bv::=b]eb subst_eb e bv b" 

instantiation e :: has_subst_b
begin
definition "subst_b = subst_eb"

instance proof
  fix j::atom and i::bv and  x::b and t::e
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
  proof (induct t rule: e.induct)
    case (AE_val v)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def e.supp v.supp  
        e.fresh has_subst_b_class.fresh_subst_if subst_b_e_def subst_b_v_def
      by metis
  next
    case (AE_app f v)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def 
        e.supp v.supp  has_subst_b_class.fresh_subst_if subst_b_v_def 
      by (metis (mono_tags, opaque_lifting) e.fresh(2))
  next
    case (AE_appP f b' v)
    then show ?case unfolding subst_eb.simps   subst_b_e_def e.fresh using
        fresh_def pure_fresh subst_b_e_def e.supp v.supp
        e.fresh has_subst_b_class.fresh_subst_if subst_b_b_def subst_vb_def   by (metis subst_b_v_def)
  next
    case (AE_op opp v1 v2)
    then show ?case unfolding subst_eb.simps   subst_b_e_def e.fresh using
        fresh_def pure_fresh subst_b_e_def e.supp v.supp fresh_e_opp_all
        e.fresh has_subst_b_class.fresh_subst_if subst_b_b_def subst_vb_def   by (metis subst_b_v_def)  
  next
    case (AE_concat x1a x2)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def e.supp v.supp  
        has_subst_b_class.fresh_subst_if subst_b_v_def 
      by (metis subst_vb.simps(5))
  next
    case (AE_split x1a x2)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def e.supp v.supp  
        has_subst_b_class.fresh_subst_if subst_b_v_def 
      by (metis subst_vb.simps(5))
  next
    case (AE_fst x)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def e.supp v.supp  has_subst_b_class.fresh_subst_if subst_b_v_def  by metis
  next
    case (AE_snd x)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def e.supp v.supp using  has_subst_b_class.fresh_subst_if subst_b_v_def  by metis
  next
    case (AE_mvar x)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def e.supp v.supp  by auto
  next
    case (AE_len x)
    then show ?case using subst_eb.simps fresh_def pure_fresh subst_b_e_def e.supp v.supp   using  has_subst_b_class.fresh_subst_if subst_b_v_def  by metis
  qed

  fix a::bv and tm::e and x::b
  show "atom a tm ==> subst_b tm a x = tm"
    apply(induct tm rule: e.induct)
             apply( auto simp add: fresh_at_base subst_eb.simps subst_b_e_def)
    using has_subst_b_class.fresh_subst_if  subst_b_b_def e.fresh 
    using has_subst_b_class.forget_subst subst_b_v_def apply metis+
    done

  fix a::bv and tm::e
  show "subst_b tm a (B_var a) = tm" using subst_bb.simps  subst_b_b_def 
    apply (induct tm rule: e.induct)
             apply(auto simp add: fresh_at_base subst_eb.simps subst_b_e_def)
    using has_subst_b_class.fresh_subst_if  subst_b_b_def e.fresh 
    using has_subst_b_class.subst_id subst_b_v_def apply metis+
    done

  fix p::perm and x1::bv and v::b and t1::e
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" 
    apply(induct tm rule: e.induct)
             apply( auto simp add: fresh_at_base subst_bb.simps subst_b_b_def )
    using has_subst_b_class.eqvt  subst_b_b_def e.fresh 
    using has_subst_b_class.eqvt 
    by (simp add: subst_b_e_def)+

  fix  bv::bv and c::e and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    apply (induct c rule: e.induct)
             apply(auto simp add: fresh_at_base  subst_eb.simps subst_b_e_def subst_b_v_def  permute_pure pure_supp )
    using  flip_fresh_fresh permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_v_def  subst_b_b_def 
      flip_fresh_fresh subst_b_τ_def apply metis
    apply (metis (full_types) opp.perm_simps  opp.strong_exhaust)
    done

  fix bv::bv and c::e and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
    apply (induct c rule: e.induct)
             apply(auto simp add: fresh_at_base  subst_eb.simps subst_b_e_def subst_b_v_def  permute_pure pure_supp )
    using  flip_fresh_fresh permute_flip_cancel2 has_subst_b_class.flip_subst subst_b_v_def  subst_b_b_def 
      flip_fresh_fresh subst_b_τ_def apply simp

    apply (metis (full_types) opp.perm_simps  opp.strong_exhaust)
    done
qed
end

section Statements

nominal_function (default "case_sum (λx. Inl undefined) (case_sum (λx. Inl undefined) (λx. Inr undefined))")
  subst_sb :: "s ==> bv ==> b ==> s"
  and subst_branchb :: "branch_s ==> bv ==> b ==> branch_s" 
  and subst_branchlb :: "branch_list ==> bv ==> b ==> branch_list"
  where
    "subst_sb (AS_val v') bv b = (AS_val (subst_vb v' bv b))"
  | "subst_sb (AS_let y e s) bv b = (AS_let y (e[bv::=b]eb) (subst_sb s bv b ))"  
  | "subst_sb (AS_let2 y t s1 s2) bv b = (AS_let2 y (subst_tb t bv b) (subst_sb s1 bv b ) (subst_sb s2 bv b))"  
  | "subst_sb (AS_match v' cs) bv b = AS_match (subst_vb v' bv b) (subst_branchlb cs bv b)"
  | "subst_sb (AS_assign y v') bv b = AS_assign y (subst_vb v' bv b)"
  | "subst_sb (AS_if v' s1 s2) bv b = (AS_if (subst_vb v' bv b) (subst_sb s1 bv b ) (subst_sb s2 bv b ) )"  
  | "subst_sb (AS_var u τ v' s) bv b = AS_var u (subst_tb τ bv b) (subst_vb v' bv b) (subst_sb s bv b )"
  | "subst_sb (AS_while s1 s2) bv b = AS_while (subst_sb s1 bv b ) (subst_sb s2 bv b )"
  | "subst_sb (AS_seq s1 s2) bv b = AS_seq (subst_sb s1 bv b ) (subst_sb s2 bv b )"
  | "subst_sb (AS_assert c s) bv b = AS_assert (subst_cb c bv b ) (subst_sb s bv b )"

"subst_branchb (AS_branch dc x1 s') bv b = AS_branch dc x1 (subst_sb s' bv b)"

"subst_branchlb (AS_final sb) bv b = AS_final (subst_branchb sb bv b )"
"subst_branchlb (AS_cons sb ssb) bv b = AS_cons (subst_branchb sb bv b) (subst_branchlb ssb bv b)"

                      apply (simp add: eqvt_def subst_sb_subst_branchb_subst_branchlb_graph_aux_def )                    
                      apply (auto,metis s_branch_s_branch_list.exhaust s_branch_s_branch_list.exhaust(2) old.sum.exhaust surj_pair)

proof(goal_cases)

  have eqvt_at_proj: " s xa va . eqvt_at subst_sb_subst_branchb_subst_branchlb_sumC (Inl (s, xa, va)) ==>
           eqvt_at (λa. projl (subst_sb_subst_branchb_subst_branchlb_sumC (Inl a))) (s, xa, va)"
    apply(simp only: eqvt_at_def)
    apply(rule)
    apply(subst Projl_permute)
     apply(thin_tac _)+
     apply(simp add: subst_sb_subst_branchb_subst_branchlb_sumC_def)
     apply(simp add: THE_default_def)
     apply(case_tac "Ex1 (subst_sb_subst_branchb_subst_branchlb_graph (Inl (s,xa,va)))")
      apply simp
      apply(auto)[1]
      apply(erule_tac x="x" in allE)
      apply simp
      apply(cases rule: subst_sb_subst_branchb_subst_branchlb_graph.cases)    
                   apply(assumption)
                  apply(rule_tac x="Sum_Type.projl x" in exI,clarify,rule the1_equality,blast,simp (no_asm) only: sum.sel)+
        apply(blast)+
    apply(simp)+      
    done
  {
    case (1 y s bv b ya sa c)
    moreover have  "atom y (bv, b) atom ya (bv, b)" using x_fresh_b x_fresh_bv fresh_Pair by simp  
    ultimately show ?case 
      using eqvt_triple eqvt_at_proj by metis
  next
    case (2 y s1 s2 bv b ya s2a c)
    moreover have  "atom y (bv, b) atom ya (bv, b)" using x_fresh_b x_fresh_bv   fresh_Pair by simp
    ultimately show ?case 
      using eqvt_triple eqvt_at_proj by metis
  next
    case (3 u s bv b ua sa c)
    moreover have  "atom u (bv, b) atom ua (bv, b)" using x_fresh_b x_fresh_bv   fresh_Pair by simp
    ultimately show ?case using eqvt_triple eqvt_at_proj by metis
  next
    case (4 x1 s' bv b x1a s'a c)
    moreover have  "atom x1 (bv, b) atom x1a (bv, b)" using x_fresh_b x_fresh_bv   fresh_Pair by simp
    ultimately show ?case using eqvt_triple eqvt_at_proj by metis
  }
qed

nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_sb_abbrev :: "s ==> bv ==> b ==> s" (_[_::=_]sb [1000,50,501000)
  where 
    "b[bv::=b']sb subst_sb b bv b'" 

lemma fresh_subst_sb_if [simp]: 
  "(j (subst_sb A i x )) = ((atom i A j A) (j x (j A j = atom i)))" and
  "(j (subst_branchb B i x )) = ((atom i B j B) (j x (j B j = atom i)))"  and
  "(j (subst_branchlb C i x )) = ((atom i C j C) (j x (j C j = atom i)))"  
proof (nominal_induct A and B and C avoiding: i x rule: s_branch_s_branch_list.strong_induct)
  case (AS_branch x1 x2 x3)
  have " (j subst_branchb (AS_branch x1 x2 x3) i x ) = (j (AS_branch x1 x2 (subst_sb x3 i x)))" by auto
  also have "... = ((j x3[i::=x]sb j set [atom x2]) j x1)" using s_branch_s_branch_list.fresh by auto
  also have "... = ((atom i AS_branch x1 x2 x3 j AS_branch x1 x2 x3) j x (j AS_branch x1 x2 x3 j = atom i))"  
    using subst_branchb.simps(1) s_branch_s_branch_list.fresh(1)  fresh_at_base has_subst_b_class.fresh_subst_if list.distinct list.set_cases set_ConsD subst_b_τ_def 
      v.fresh AS_branch
  proof -
    have f1: "cs b. atom (b::bv) (cs::char list)" using pure_fresh by auto

    then have "j x atom i = j ((j x3[i::=x]sb j set [atom x2]) j x1) = (atom i AS_branch x1 x2 x3 j AS_branch x1 x2 x3 j x (j AS_branch x1 x2 x3 j = atom i))"
      by (metis (full_types) AS_branch.hyps(3))
    then have "j x ((j x3[i::=x]sb j set [atom x2]) j x1) = (atom i AS_branch x1 x2 x3 j AS_branch x1 x2 x3 j x (j AS_branch x1 x2 x3 j = atom i))"
      using  AS_branch.hyps s_branch_s_branch_list.fresh by metis
    moreover
    { assume "¬ j x"
      have ?thesis
        using f1 AS_branch.hyps(2) AS_branch.hyps(3by force  }
    ultimately show ?thesis
      by satx 
  qed   
  finally show ?case by auto  
next
  case (AS_cons cs css i x)
  show ?case 
    unfolding subst_branchlb.simps s_branch_s_branch_list.fresh 
    using AS_cons by auto
next
  case (AS_val xx)
  then show ?case using  subst_sb.simps(1) s_branch_s_branch_list.fresh has_subst_b_class.fresh_subst_if subst_b_b_def subst_b_v_def by metis
next
  case (AS_let x1 x2 x3)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh  fresh_at_base has_subst_b_class.fresh_subst_if list.distinct list.set_cases set_ConsD subst_b_e_def 
    by fastforce
next
  case (AS_let2 x1 x2 x3 x4)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh  fresh_at_base has_subst_b_class.fresh_subst_if list.distinct list.set_cases set_ConsD subst_b_τ_def
    by fastforce
next
  case (AS_if x1 x2 x3)
  then show ?case unfolding   subst_sb.simps s_branch_s_branch_list.fresh using
      has_subst_b_class.fresh_subst_if  subst_b_v_def   by metis
next
  case (AS_var u t v s)

  have "(((atom i s j s j x (j s j = atom i)) j set [atom u]) j t[i::=x]\<tau>b j v[i::=x]vb) =
          (((atom i s j s j x (j s j = atom i)) j set [atom u])
                    ((atom i t j t j x (j t j = atom i)))
                    ((atom i v j v j x (j v j = atom i))))" 
    using    has_subst_b_class.fresh_subst_if  subst_b_v_def  subst_b_τ_def by metis
  also have "... = (((atom i s atom i set [atom u]) atom i t atom i v)
               (j s j set [atom u]) j t j v j x ((j s j set [atom u]) j t j v j = atom i))" 
    using u_fresh_b by auto
  finally show ?case using  subst_sb.simps s_branch_s_branch_list.fresh AS_var 
    by simp
next
  case (AS_assign u v )
  then show ?case unfolding   subst_sb.simps s_branch_s_branch_list.fresh using
      has_subst_b_class.fresh_subst_if  subst_b_v_def by force
next
  case (AS_match v cs)
  have " j (AS_match v cs)[i::=x]sb = j (AS_match (subst_vb v i x) (subst_branchlb cs i x ))" using subst_sb.simps by auto
  also have "... = (j (subst_vb v i x) j (subst_branchlb cs i x ))" using s_branch_s_branch_list.fresh by simp
  also have "... = (j (subst_vb v i x) ((atom i cs j cs) j x (j cs j = atom i)))" using  AS_match[of i x] by auto
  also have "... = (atom i AS_match v cs j AS_match v cs j x (j AS_match v cs j = atom i))" 
    by (metis (no_types) s_branch_s_branch_list.fresh has_subst_b_class.fresh_subst_if subst_b_v_def) (* 93 ms *)  
  finally show ?case by auto
next
  case (AS_while x1 x2)
  then show ?case by auto
next
  case (AS_seq x1 x2)
  then show ?case by auto
next
  case (AS_assert x1 x2)
  then show ?case unfolding subst_sb.simps  s_branch_s_branch_list.fresh 
    using  fresh_at_base has_subst_b_class.fresh_subst_if list.distinct list.set_cases set_ConsD subst_b_e_def 
    by (metis subst_b_c_def)   
qed(auto+)

lemma 
  forget_subst_sb[simp]: "atom a A ==> subst_sb A a x = A" and
  forget_subst_branchb [simp]: "atom a B ==> subst_branchb B a x = B" and 
  forget_subst_branchlb[simp]: "atom a C ==> subst_branchlb C a x = C"
proof (nominal_induct A and B and C avoiding: a x rule: s_branch_s_branch_list.strong_induct)
  case (AS_let x1 x2 x3)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_let2 x1 x2 x3 x4)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_τ_def by force
next
  case (AS_var x1 x2 x3 x4)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def  using subst_b_τ_def 
  proof -
    have f1: "(atom a x4 atom a set [atom x1]) atom a x2 atom a x3"
      using AS_var.prems s_branch_s_branch_list.fresh  by simp
    then have "atom a x4"
      by (metis (no_types) "Nominal-Utils.fresh_star_singleton" AS_var.hyps(1) empty_set fresh_star_def list.simps(15) not_self_fresh) (* 46 ms *)
    then show ?thesis
      using f1 by (metis AS_var.hyps(3) has_subst_b_class.forget_subst subst_b_τ_def subst_b_v_def subst_sb.simps(7)) (* 62 ms *)
  qed
next
  case (AS_branch x1 x2 x3)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_cons x1 x2 x3 x4)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_val x)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_if x1 x2 x3)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_assign x1 x2)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_match x1 x2)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_while x1 x2)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_seq x1 x2)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def by force
next
  case (AS_assert c s)
  then show ?case unfolding  subst_sb.simps using
      s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.forget_subst subst_b_v_def  subst_b_c_def subst_cb.simps  by force
qed(auto+)

lemma   subst_sb_id: "subst_sb A a (B_var a) = A" and
  subst_branchb_id [simp]: "subst_branchb B a (B_var a) = B" and
  subst_branchlb_id: "subst_branchlb C a (B_var a) = C"
proof(nominal_induct A and B and C avoiding: a  rule: s_branch_s_branch_list.strong_induct)
  case (AS_branch x1 x2 x3)
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def 
    by simp
next
  case (AS_cons x1 x2 )
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by simp
next
  case (AS_val x)
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by metis
next
  case (AS_if x1 x2 x3)
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by metis
next
  case (AS_assign x1 x2)
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by metis
next
  case (AS_match x1 x2)
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by metis
next
  case (AS_while x1 x2)
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by metis
next
  case (AS_seq x1 x2)
  then show ?case  using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by metis
next
  case (AS_let x1 x2 x3)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_e_def has_subst_b_class.subst_id by metis
next
  case (AS_let2 x1 x2 x3 x4)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id by metis
next
  case (AS_var x1 x2 x3 x4)
  then show ?case using subst_sb.simps s_branch_s_branch_list.fresh subst_b_τ_def has_subst_b_class.subst_id subst_b_v_def by metis
next
  case (AS_assert c s )
  then show ?case unfolding subst_sb.simps using s_branch_s_branch_list.fresh subst_b_c_def has_subst_b_class.subst_id by metis
qed (auto)

lemma flip_subst_s:
  fixes  bv::bv and s::s and cs::branch_s and z::bv
  shows   "atom bv s ==> ((bv z) s) = s[z::=B_var bv]sb"  and
    "atom bv cs ==> ((bv z) cs) = subst_branchb cs z (B_var bv) " and
    "atom bv css ==> ((bv z) css) = subst_branchlb css z (B_var bv) "

proof(nominal_induct s and cs and css  rule: s_branch_s_branch_list.strong_induct)
  case (AS_branch x1 x2 x3)
  hence "((bv z) x1) = x1"  using pure_fresh fresh_at_base flip_fresh_fresh  by metis
  moreover have "((bv z) x2) = x2" using  fresh_at_base flip_fresh_fresh[of bv x2 z] AS_branch  by auto
  ultimately show ?case unfolding  s_branch_s_branch_list.perm_simps subst_branchb.simps using s_branch_s_branch_list.fresh(1) AS_branch by auto
next
  case (AS_cons x1 x2 )
  hence "((bv z) x1) = subst_branchb x1 z (B_var bv)"  using pure_fresh fresh_at_base flip_fresh_fresh  s_branch_s_branch_list.fresh(13)  by metis
  moreover have "((bv z) x2) = subst_branchlb x2 z (B_var bv)" using  fresh_at_base flip_fresh_fresh[of bv x2 z] AS_cons s_branch_s_branch_list.fresh by metis
  ultimately show ?case unfolding  s_branch_s_branch_list.perm_simps subst_branchb.simps using s_branch_s_branch_list.fresh(1) AS_cons by auto
next
  case (AS_val x)
  then show ?case unfolding  s_branch_s_branch_list.perm_simps subst_branchb.simps using flip_subst subst_b_v_def by simp
next
  case (AS_let x1 x2 x3)
  moreover hence "((bv z) x1) = x1" using fresh_at_base flip_fresh_fresh[of bv x1 z]  by auto
  ultimately show ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def s_branch_s_branch_list.fresh by auto 
next
  case (AS_let2 x1 x2 x3 x4)
  moreover hence "((bv z) x1) = x1" using fresh_at_base flip_fresh_fresh[of bv x1 z]  by auto
  ultimately show ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst s_branch_s_branch_list.fresh(5) subst_b_τ_def by auto
next
  case (AS_if x1 x2 x3) 
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_var x1 x2 x3 x4)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def subst_b_τ_def s_branch_s_branch_list.fresh fresh_at_base flip_fresh_fresh[of bv x1 z] by auto
next
  case (AS_assign x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh fresh_at_base flip_fresh_fresh[of bv x1 z] by auto
next
  case (AS_match x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_while x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_seq x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_assert x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_c_def subst_b_v_def s_branch_s_branch_list.fresh by simp
qed(auto)

lemma flip_subst_subst_s:
  fixes  bv::bv and s::s and cs::branch_s and z::bv
  shows   "atom bv s ==> ((bv z) s)[bv::=v]sb = s[z::=v]sb"    and
    "atom bv cs ==> subst_branchb ((bv z) cs) bv v = subst_branchb cs z v" and
    "atom bv css ==> subst_branchlb ((bv z) css) bv v = subst_branchlb css z v " 
proof(nominal_induct s  and cs and css rule: s_branch_s_branch_list.strong_induct)
  case (AS_branch x1 x2 x3)
  hence "((bv z) x1) = x1"  using pure_fresh fresh_at_base flip_fresh_fresh  by metis
  moreover have "((bv z) x2) = x2" using  fresh_at_base flip_fresh_fresh[of bv x2 z] AS_branch  by auto
  ultimately show ?case unfolding  s_branch_s_branch_list.perm_simps subst_branchb.simps using s_branch_s_branch_list.fresh(1) AS_branch by auto
next
  case (AS_cons x1 x2 )
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_branchlb.simps
    using s_branch_s_branch_list.fresh(1) AS_cons by auto

next
  case (AS_val x)
  then show ?case unfolding  s_branch_s_branch_list.perm_simps subst_branchb.simps using flip_subst subst_b_v_def by simp
next
  case (AS_let x1 x2 x3)
  moreover hence "((bv z) x1) = x1" using fresh_at_base flip_fresh_fresh[of bv x1 z]  by auto
  ultimately show ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst_subst subst_b_e_def s_branch_s_branch_list.fresh by force
next
  case (AS_let2 x1 x2 x3 x4)
  moreover hence "((bv z) x1) = x1" using fresh_at_base flip_fresh_fresh[of bv x1 z]  by auto
  ultimately show ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst s_branch_s_branch_list.fresh(5) subst_b_τ_def by auto
next
  case (AS_if x1 x2 x3) 
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_var x1 x2 x3 x4)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def subst_b_τ_def s_branch_s_branch_list.fresh fresh_at_base flip_fresh_fresh[of bv x1 z] by auto
next
  case (AS_assign x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh fresh_at_base flip_fresh_fresh[of bv x1 z] by auto
next
  case (AS_match x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_while x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_seq x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_v_def s_branch_s_branch_list.fresh by auto
next
  case (AS_assert x1 x2)
  thus ?case 
    unfolding  s_branch_s_branch_list.perm_simps subst_sb.simps 
    using flip_subst subst_b_e_def subst_b_c_def s_branch_s_branch_list.fresh by auto
qed(auto)

instantiation s :: has_subst_b
begin
definition "subst_b = (λs bv b. subst_sb s bv b)"

instance proof
  fix j::atom and i::bv and  x::b and t::s
  show  "j subst_b t i x = ((atom i t j t) (j x (j t j = atom i)))" 
    using fresh_subst_sb_if subst_b_s_def by metis

  fix a::bv and tm::s and x::b
  show "atom a tm ==> subst_b tm a x = tm" using subst_b_s_def forget_subst_sb by metis

  fix a::bv and tm::s
  show "subst_b tm a (B_var a) = tm" using subst_b_s_def  subst_sb_id   by metis

  fix p::perm and x1::bv and v::b and t1::s
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" using subst_b_s_def subst_sb_subst_branchb_subst_branchlb.eqvt by metis

  fix  bv::bv and c::s and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    using subst_b_s_def flip_subst_s by metis

  fix bv::bv and c::s and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
    using flip_subst_subst_s subst_b_s_def by metis
qed
end

section Function Type

nominal_function subst_ft_b :: "fun_typ ==> bv ==> b ==> fun_typ" where
  "subst_ft_b ( AF_fun_typ z b c t (s::s)) x v = AF_fun_typ z (subst_bb b x v) (subst_cb c x v) t[x::=v]\<tau>b s[x::=v]sb"
     apply(simp add: eqvt_def subst_ft_b_graph_aux_def )
    apply(simp add:fun_typ.strong_exhaust,auto )
  apply(rule_tac y=a and c="(a,b)" in fun_typ.strong_exhaust)
  apply (auto simp: eqvt_at_def fresh_star_def fresh_Pair fresh_at_base)
  done

nominal_termination (eqvt) by lexicographic_order

nominal_function subst_ftq_b :: "fun_typ_q ==> bv ==> b ==> fun_typ_q" where
  "atom bv (x,v) ==> subst_ftq_b (AF_fun_typ_some bv ft) x v = (AF_fun_typ_some bv (subst_ft_b ft x v))" 
|  "subst_ftq_b (AF_fun_typ_none ft) x v = (AF_fun_typ_none (subst_ft_b ft x v))" 
       apply(simp add: eqvt_def subst_ftq_b_graph_aux_def )
      apply(simp add:fun_typ_q.strong_exhaust,auto )
  apply(rule_tac y=a and c="(aa,b)" in fun_typ_q.strong_exhaust)
  by (auto simp: eqvt_at_def fresh_star_def fresh_Pair fresh_at_base)
nominal_termination (eqvt) by lexicographic_order

instantiation fun_typ :: has_subst_b
begin
definition "subst_b = subst_ft_b"

text Note: Using just simp in the second apply unpacks and gives a single goal
  auto gives 43 non-intuitive goals. These goals are easier to solve
  tedious, however they that it clear if a mistake is made in the definition of the function.
  example, I saw that one of the goals was
  through with metis and the next wasn't.
  turned out the definition of the function itself was wrong


instance proof
  fix j::atom and i::bv and  x::b and t::fun_typ
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
    apply(nominal_induct t avoiding: i x rule:fun_typ.strong_induct)
    apply(auto simp add: subst_b_fun_typ_def )       
    by(metis fresh_subst_if subst_b_s_def subst_b_τ_def subst_b_b_def subst_b_c_def)+

  fix a::bv and tm::fun_typ and x::b
  show "atom a tm ==> subst_b tm a x = tm"
    apply (nominal_induct tm avoiding: a x rule: fun_typ.strong_induct)
    apply(simp add: subst_b_fun_typ_def Abs1_eq_iff')
    using subst_b_b_def  subst_b_fun_typ_def subst_b_τ_def subst_b_c_def subst_b_s_def
      forget_subst fresh_at_base list.set_cases neq_Nil_conv set_ConsD
      subst_ft_b.simps  by metis

  fix a::bv and tm::fun_typ
  show "subst_b tm a (B_var a) = tm" 
    apply (nominal_induct tm rule: fun_typ.strong_induct)
    apply(simp add: subst_b_fun_typ_def Abs1_eq_iff',auto)
    using subst_b_b_def  subst_b_fun_typ_def subst_b_τ_def subst_b_c_def subst_b_s_def
      forget_subst fresh_at_base list.set_cases neq_Nil_conv set_ConsD
      subst_ft_b.simps 
    by (metis has_subst_b_class.subst_id)+

  fix p::perm and x1::bv and v::b and t1::fun_typ
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v) " 
    apply (nominal_induct t1 avoiding: x1 v rule: fun_typ.strong_induct)
    by(auto simp add: subst_b_fun_typ_def Abs1_eq_iff' fun_typ.perm_simps)

  fix  bv::bv and c::fun_typ and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    apply (nominal_induct c avoiding: z bv rule: fun_typ.strong_induct)
    by(auto simp add: subst_b_fun_typ_def Abs1_eq_iff' fun_typ.perm_simps subst_b_b_def subst_b_c_def  subst_b_τ_def  subst_b_s_def)

  fix bv::bv and c::fun_typ and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
    apply (nominal_induct c avoiding:  bv v z rule: fun_typ.strong_induct)
    apply(auto simp add: subst_b_fun_typ_def Abs1_eq_iff' fun_typ.perm_simps subst_b_b_def subst_b_c_def  subst_b_τ_def  subst_b_s_def flip_subst_subst flip_subst)
    using  subst_b_fun_typ_def Abs1_eq_iff' fun_typ.perm_simps subst_b_b_def subst_b_c_def  subst_b_τ_def  subst_b_s_def flip_subst_subst flip_subst 
    using flip_subst_s(1) flip_subst_subst_s(1by auto
qed
end

instantiation fun_typ_q :: has_subst_b
begin
definition "subst_b = subst_ftq_b"

instance proof
  fix j::atom and i::bv and  x::b and t::fun_typ_q
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
    apply (nominal_induct t avoiding: i x j rule: fun_typ_q.strong_induct,auto simp add: subst_b_fun_typ_q_def subst_ftq_b.simps)
    using  fresh_subst_if subst_b_fun_typ_q_def subst_b_s_def subst_b_τ_def subst_b_b_def subst_b_c_def subst_b_fun_typ_def apply metis+
    done

  fix a::bv and t::fun_typ_q and x::b
  show "atom a t ==> subst_b t a x = t"
    apply (nominal_induct t avoiding: a x  rule: fun_typ_q.strong_induct)
     apply(auto simp add: subst_b_fun_typ_q_def subst_ftq_b.simps Abs1_eq_iff') 
    using  forget_subst subst_b_fun_typ_q_def subst_b_s_def subst_b_τ_def subst_b_b_def subst_b_c_def subst_b_fun_typ_def eqvt by metis+

  fix p::perm and x1::bv and v::b and t::fun_typ_q
  show "p subst_b t x1 v = subst_b (p t) (p x1) (p v) " 
    apply (nominal_induct t avoiding: x1 v  rule: fun_typ_q.strong_induct)
    by(auto simp add: subst_b_fun_typ_q_def subst_ftq_b.simps Abs1_eq_iff') 

  fix a::bv and tm::fun_typ_q
  show "subst_b tm a (B_var a) = tm" 
    apply (nominal_induct tm avoiding: a rule: fun_typ_q.strong_induct)
     apply(auto simp add: subst_b_fun_typ_q_def subst_ftq_b.simps Abs1_eq_iff')
    using subst_id subst_b_b_def  subst_b_fun_typ_def subst_b_τ_def subst_b_c_def subst_b_s_def
      forget_subst fresh_at_base list.set_cases neq_Nil_conv set_ConsD
      subst_ft_b.simps by metis+

  fix  bv::bv and c::fun_typ_q and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
    apply (nominal_induct c avoiding: z bv  rule: fun_typ_q.strong_induct)
     apply(auto simp add: subst_b_fun_typ_q_def subst_ftq_b.simps Abs1_eq_iff') 
    using  forget_subst subst_b_fun_typ_q_def subst_b_s_def subst_b_τ_def subst_b_b_def subst_b_c_def subst_b_fun_typ_def eqvt by metis+

  fix bv::bv and c::fun_typ_q and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
    apply (nominal_induct c avoiding: z v bv  rule: fun_typ_q.strong_induct)
     apply(auto simp add: subst_b_fun_typ_q_def subst_ftq_b.simps Abs1_eq_iff') 
    using  flip_subst flip_subst_subst forget_subst subst_b_fun_typ_q_def subst_b_s_def subst_b_τ_def subst_b_b_def subst_b_c_def subst_b_fun_typ_def eqvt by metis+

qed
end

section Contexts

subsection Immutable Variables
nominal_function subst_gb :: ==> bv ==> b ==> Γ" where
  "subst_gb GNil _ _ = GNil"
"subst_gb ((y,b',c)#\<Gamma>Γ) bv b = ((y,b'[bv::=b]bb,c[bv::=b]cb)#\<Gamma> (subst_gb Γ bv b))"
       apply (simp add: eqvt_def subst_gb_graph_aux_def )+
     apply auto
  apply (insert Γ.exhaust neq_GNil_conv, force)
  done
nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_gb_abbrev :: ==> bv ==> b ==> Γ" (_[_::=_]\Γb [1000,50,501000)
  where 
    "g[bv::=b']\<Gamma>b subst_gb g bv b'" 

instantiation Γ :: has_subst_b
begin
definition "subst_b = subst_gb"

instance proof
  fix j::atom and i::bv and  x::b and t::Γ
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
  proof(induct t rule: Γ_induct)
    case GNil
    then show ?case using fresh_GNil  subst_gb.simps  fresh_def pure_fresh subst_b_Γ_def has_subst_b_class.fresh_subst_if fresh_GNil fresh_GCons by metis
  next
    case (GCons x' b' c' Γ')
    have *: "atom i x' " using  fresh_at_base by simp

    have "j subst_b ((x', b', c') #\<Gamma> Γ') i x = j ((x', b'[i::=x]bb, c'[i::=x]cb) #\<Gamma> (subst_b Γ' i x))" using subst_gb.simps  subst_b_Γ_def by auto
    also have "... = (j ((x', b'[i::=x]bb, c'[i::=x]cb)) (j (subst_b Γ' i x)))" using fresh_GCons by auto
    also have "... = (((j x') (j b'[i::=x]bb) (j c'[i::=x]cb)) (j (subst_b Γ' i x)))"  by auto
    also have "... = (((j x') ((atom i b' j b' j x (j b' j = atom i)))
                                   ((atom i c' j c' j x (j c' j = atom i)))
                                   ((atom i Γ' j Γ' j x (j Γ' j = atom i)))))" 
      using fresh_subst_if[of j b' i x] fresh_subst_if[of j c' i x] GCons subst_b_b_def  subst_b_c_def  by simp
    also have "... = ((atom i (x', b', c') #\<Gamma> Γ' j (x', b', c') #\<Gamma> Γ') (j x (j (x', b', c') #\<Gamma> Γ' j = atom i)))" using * fresh_GCons fresh_prod3 by metis

    finally show ?case  by auto
  qed

  fix a::bv and tm::Γ and x::b
  show "atom a tm ==> subst_b tm a x = tm"
  proof (induct tm rule: Γ_induct)
    case GNil
    then show ?case using  subst_gb.simps subst_b_Γ_def by auto
  next
    case (GCons x' b' c' Γ')
    have *:"b'[a::=x]bb = b' c'[a::=x]cb = c'" using GCons fresh_GCons[of "atom a"] fresh_prod3[of "atom a"] has_subst_b_class.forget_subst  subst_b_b_def subst_b_c_def by metis
    have "subst_b ((x', b', c') #\<Gamma> Γ') a x = ((x', b'[a::=x]bb, c'[a::=x]cb) #\<Gamma> (subst_b Γ' a x))" using  subst_b_Γ_def subst_gb.simps by auto
    also have "... = ((x', b', c') #\<Gamma> Γ')" using * GCons  fresh_GCons[of "atom a"]  by aut
    finally show ?case using   has_subst_b_class.forget_subst fresh_GCons fresh_prod3 GCons subst_b_Γ_def has_subst_b_class.forget_subst[of a b' x] fresh_prod3[of "atom a"by argo
  qed

  fix a::bv and tm::Γ
  show "subst_b tm a (B_var a) = tm"
  proof(induct tm rule: Γ_induct)
    case GNil
    then show ?case using  subst_gb.simps subst_b_Γ_def by auto
  next
    case (GCons x' b' c' Γ')
    then show ?case using    has_subst_b_class.subst_id  subst_b_Γ_def subst_b_b_def subst_b_c_def subst_gb.simps by metis
  qed

  fix p::perm and x1::bv and v::b and t1::Γ
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" 
  proof (induct tm rule: Γ_induct)
    case GNil
    then show ?case using subst_b_Γ_def subst_gb.simps by simp
  next
    case (GCons x' b' c' Γ')
    then show ?case using subst_b_Γ_def subst_gb.simps has_subst_b_class.eqvt by argo
  qed

  fix  bv::bv and c::Γ and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
  proof (induct c rule: Γ_induct)
    case GNil
    then show ?case using subst_b_Γ_def subst_gb.simps by auto
  next
    case (GCons x b c Γ')   
    have *:"(bv z) (x, b, c) = (x, (bv z) b, (bv z) c)" using flip_bv_x_cancel by auto
    then show ?case 
      unfolding subst_gb.simps subst_b_Γ_def permute_Γ.simps  * 
      using GCons subst_b_Γ_def subst_gb.simps flip_subst subst_b_b_def subst_b_c_def fresh_GCons by auto
  qed

  fix bv::bv and c::Γ and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
  proof (induct c rule: Γ_induct)
    case GNil
    then show ?case using subst_b_Γ_def subst_gb.simps by auto
  next
    case (GCons x b c Γ')   
    have *:"(bv z) (x, b, c) = (x, (bv z) b, (bv z) c)" using flip_bv_x_cancel by auto
    then show ?case 
      unfolding subst_gb.simps subst_b_Γ_def permute_Γ.simps  * 
      using GCons subst_b_Γ_def subst_gb.simps flip_subst subst_b_b_def subst_b_c_def fresh_GCons by auto
  qed
qed
end

lemma subst_b_base_for_lit:
  "(base_for_lit l)[bv::=b]bb = base_for_lit l"
  using base_for_lit.simps l.strong_exhaust 
  by (metis subst_bb.simps(2) subst_bb.simps(3) subst_bb.simps(6) subst_bb.simps(7))

lemma subst_b_lookup:
  assumes "Some (b, c) = lookup Γ x"
  shows " Some (b[bv::=b']bb, c[bv::=b']cb) = lookup Γ[bv::=b']\<Gamma>b x"
  using assms by(induct Γ rule: Γ_induct, auto)

lemma subst_g_b_x_fresh:
  fixes x::x and b::b and Γ::Γ and bv::bv
  assumes "atom x Γ"
  shows  "atom x Γ[bv::=b]\<Gamma>b"
  using subst_b_fresh_x subst_b_Γ_def assms by metis

subsection Mutable Variables

nominal_function subst_db :: ==> bv ==> b ==> Δ" where
  "subst_db []\<Delta> _ _ = []\<Delta>"
"subst_db ((u,t) #\<Delta> Δ) bv b = ((u,t[bv::=b]\<tau>b) #\<Delta> (subst_db Δ bv b))"
       apply (simp add: eqvt_def subst_db_graph_aux_def,auto )
  using list.exhaust delete_aux.elims
  using neq_DNil_conv by fastforce
nominal_termination (eqvt) by lexicographic_order

abbreviation 
  subst_db_abbrev :: ==> bv ==> b ==> Δ" (_[_::=_]\Δb [1000,50,501000)
  where 
    "Δ[bv::=b]\<Delta>b subst_db Δ bv b" 

instantiation Δ :: has_subst_b
begin
definition "subst_b = subst_db"

instance proof
  fix j::atom and i::bv and  x::b and t::Δ
  show  "j subst_b t i x = (atom i t j t j x (j t j = atom i))"
  proof(induct t rule: Δ_induct)
    case DNil
    then show ?case using fresh_DNil  subst_db.simps  fresh_def pure_fresh subst_b_Δ_def has_subst_b_class.fresh_subst_if fresh_DNil fresh_DCons by metis
  next
    case (DCons u t Γ')
    have "j subst_b ((u, t) #\<Delta> Γ') i x = j ((u, t[i::=x]\<tau>b) #\<Delta> (subst_b Γ' i x))" using subst_db.simps  subst_b_Δ_def by auto
    also have "... = (j ((u, t[i::=x]\<tau>b)) (j (subst_b Γ' i x)))" using fresh_DCons by auto
    also have "... = (((j u) (j t[i::=x]\<tau>b)) (j (subst_b Γ' i x)))"  by auto
    also have "... = ((j u) ((atom i t j t) (j x (j t j = atom i))) (atom i Γ' j Γ' j x (j Γ' j = atom i)))" 
      using has_subst_b_class.fresh_subst_if[of j t i x] subst_b_τ_def DCons  subst_b_Δ_def by auto
    also have "... = (atom i (u, t) #\<Delta> Γ' j (u, t) #\<Delta> Γ' j x (j (u, t) #\<Delta> Γ' j = atom i))" 
      using DCons subst_db.simps(2)  has_subst_b_class.fresh_subst_if fresh_DCons subst_b_Δ_def  pure_fresh fresh_at_base by auto
    finally show ?case  by auto
  qed

  fix a::bv and tm::Δ and x::b
  show "atom a tm ==> subst_b tm a x = tm"
  proof (induct tm rule: Δ_induct)
    case DNil
    then show ?case using  subst_db.simps subst_b_Δ_def by auto
  next
    case (DCons u t Γ')
    have *:"t[a::=x]\<tau>b = t" using DCons fresh_DCons[of "atom a"] fresh_prod2[of "atom a"] has_subst_b_class.forget_subst  subst_b_τ_def by metis
    have "subst_b ((u,t) #\<Delta> Γ') a x = ((u,t[a::=x]\<tau>b) #\<Delta> (subst_b Γ' a x))" using  subst_b_Δ_def subst_db.simps by auto
    also have "... = ((u, t) #\<Delta> Γ')" using * DCons  fresh_DCons[of "atom a"]  by auto 
    finally show ?case using   
        has_subst_b_class.forget_subst fresh_DCons fresh_prod3 
        DCons subst_b_Δ_def has_subst_b_class.forget_subst[of a t x] fresh_prod3[of "atom a"by argo
  qed

  fix a::bv and tm::Δ
  show "subst_b tm a (B_var a) = tm"
  proof(induct tm rule: Δ_induct)
    case DNil
    then show ?case using  subst_db.simps subst_b_Δ_def by auto
  next
    case (DCons u t  Γ')
    then show ?case using    has_subst_b_class.subst_id  subst_b_Δ_def subst_b_τ_def subst_db.simps by metis
  qed

  fix p::perm and x1::bv and v::b and t1::Δ
  show "p subst_b t1 x1 v = subst_b (p t1) (p x1) (p v)" 
  proof (induct tm rule: Δ_induct)
    case DNil
    then show ?case using subst_b_Δ_def subst_db.simps by simp
  next
    case (DCons x' b' Γ')
    then show ?case  by argo
  qed

  fix  bv::bv and c::Δ and z::bv
  show "atom bv c ==> ((bv z) c) = c[z::=B_var bv]b"
  proof (induct c rule: Δ_induct)
    case DNil
    then show ?case using subst_b_Δ_def subst_db.simps by auto
  next
    case (DCons u t')
    then show ?case 
      unfolding subst_db.simps subst_b_Δ_def permute_Δ.simps  
      using DCons subst_b_Δ_def subst_db.simps flip_subst subst_b_τ_def flip_fresh_fresh fresh_at_base fresh_DCons flip_bv_u_cancel by simp
  qed

  fix bv::bv and c::Δ and z::bv and v::b
  show "atom bv c ==> ((bv z) c)[bv::=v]b = c[z::=v]b"
  proof (induct c rule: Δ_induct)
    case DNil
    then show ?case using subst_b_Δ_def subst_db.simps by auto
  next
    case (DCons u t')
    then show ?case 
      unfolding subst_db.simps subst_b_Δ_def permute_Δ.simps  
      using DCons subst_b_Δ_def subst_db.simps flip_subst subst_b_τ_def flip_fresh_fresh fresh_at_base fresh_DCons flip_bv_u_cancel by simp
  qed
qed
end

lemma subst_d_b_member:
  assumes "(u, τ) setD Δ" 
  shows  "(u, τ[bv::=b]\<tau>b) setD Δ[bv::=b]\<Delta>b" 
  using assms  by (induct Δ,auto)

lemmas ms_fresh_all = e.fresh s_branch_s_branch_list.fresh τ.fresh c.fresh ce.fresh v.fresh l.fresh fresh_at_base opp.fresh pure_fresh ms_fresh

lemmas fresh_intros[intro] = fresh_GNil x_not_in_b_set x_not_in_u_atoms x_fresh_b u_not_in_x_atoms bv_not_in_x_atoms u_not_in_b_atoms

lemmas subst_b_simps = subst_tb.simps subst_cb.simps subst_ceb.simps subst_vb.simps subst_bb.simps  subst_eb.simps subst_branchb.simps subst_sb.simps

lemma subst_d_b_x_fresh:
  fixes x::x and b::b and Δ::Δ and bv::bv
  assumes "atom x Δ"
  shows  "atom x Δ[bv::=b]\<Delta>b"
  using subst_b_fresh_x subst_b_Δ_def assms by metis

lemma subst_b_fresh_x:
  fixes  x::x
  shows "atom x v ==> atom x v[bv::=b']vb" and
    "atom x ce ==> atom x ce[bv::=b']ceb" and
    "atom x e ==> atom x e[bv::=b']eb" and
    "atom x c ==> atom x c[bv::=b']cb" and
    "atom x t ==> atom x t[bv::=b']\<tau>b" and
    "atom x d ==> atom x d[bv::=b']\<Delta>b" and
    "atom x g ==> atom x g[bv::=b']\<Gamma>b" and
    "atom x s ==> atom x s[bv::=b']sb"
  using fresh_subst_if x_fresh_b subst_b_v_def subst_b_ce_def subst_b_e_def subst_b_c_def subst_b_τ_def subst_b_s_def subst_g_b_x_fresh subst_d_b_x_fresh 
  by metis+

lemma subst_b_fresh_u_cls:
  fixes tm::"'a::has_subst_b" and x::u
  shows "atom x tm = atom x tm[bv::=b']b"
  using fresh_subst_if[of "atom x" tm bv b'] using u_fresh_b by auto

lemma subst_g_b_u_fresh:
  fixes x::u and b::b and Γ::Γ and bv::bv
  assumes "atom x Γ"
  shows  "atom x Γ[bv::=b]\<Gamma>b"
  using subst_b_fresh_u_cls subst_b_Γ_def assms by metis

lemma subst_d_b_u_fresh:
  fixes x::u and b::b and Γ::Δ and bv::bv
  assumes "atom x Γ"
  shows  "atom x Γ[bv::=b]\<Delta>b"
  using subst_b_fresh_u_cls subst_b_Δ_def assms by metis

lemma subst_b_fresh_u:
  fixes  x::u
  shows "atom x v ==> atom x v[bv::=b']vb" and
    "atom x ce ==> atom x ce[bv::=b']ceb" and
    "atom x e ==> atom x e[bv::=b']eb" and
    "atom x c ==> atom x c[bv::=b']cb" and
    "atom x t ==> atom x t[bv::=b']\<tau>b" and
    "atom x d ==> atom x d[bv::=b']\<Delta>b" and
    "atom x g ==> atom x g[bv::=b']\<Gamma>b" and
    "atom x s ==> atom x s[bv::=b']sb"
  using fresh_subst_if u_fresh_b subst_b_v_def subst_b_ce_def subst_b_e_def subst_b_c_def subst_b_τ_def subst_b_s_def subst_g_b_u_fresh subst_d_b_u_fresh 
  by metis+

lemma subst_db_u_fresh:
  fixes u::u and b::b and D::Δ
  assumes "atom u D"
  shows  "atom u D[bv::=b]\<Delta>b"
  using assms proof(induct D rule: Δ_induct)
  case DNil
  then show ?case by auto
next
  case (DCons u' t' D')
  then show ?case using subst_db.simps fresh_def fresh_DCons fresh_subst_if subst_b_τ_def 
    by (metis fresh_Pair u_not_in_b_atoms)
qed

lemma flip_bt_subst4:
  fixes t::τ and bv::bv 
  assumes "atom bv t" 
  shows "t[bv'::=b]\<tau>b = ((bv' bv) t)[bv::=b]\<tau>b" 
  using flip_subst_subst[OF assms,of bv' b] 
  by (simp add: flip_commute subst_b_τ_def)

lemma subst_bt_flip_sym:
  fixes t1::τ and t2::τ
  assumes "atom bv b" and "atom bv (bv1, bv2, t1, t2)" and "(bv1 bv) t1 = (bv2 bv) t2"
  shows " t1[bv1::=b]\<tau>b = t2[bv2::=b]\<tau>b"
  using assms  flip_bt_subst4[of bv t1 bv1 b ]   flip_bt_subst4 fresh_prod4 fresh_Pair by metis

end

Messung V0.5 in Prozent
C=92 H=98 G=94

¤ Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.0.38Bemerkung:  (vorverarbeitet am  2026-06-10) ¤

*Bot Zugriff






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.