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 50 kB image not shown  

Quelle  Syntax.thy

  Sprache: Isabelle
 

(*<*)
theory Syntax
  imports "Nominal2.Nominal2" "Nominal-Utils"
begin
  (*>*)

chapter Syntax

text Syntax of MiniSail programs and the contexts we use in judgements.

section Program Syntax

subsection AST Datatypes

type_synonym num_nat = nat

atom_decl x  (* Immutable variables*)
atom_decl u  (* Mutable variables *)
atom_decl bv  (* Basic-type variables *)

type_synonym f = string  (* Function name *)
type_synonym dc = string (* Data constructor *)
type_synonym tyid = string

text Basic types. Types without refinement constraints
nominal_datatype "b" =  
  B_int | B_bool | B_id tyid 
| B_pair b b  ([ _ , _ ]b)
| B_unit | B_bitvec | B_var bv
| B_app tyid b

nominal_datatype bit = BitOne | BitZero

text   Literals
nominal_datatype "l" = 
  L_num "int" | L_true | L_false | L_unit  | L_bitvec "bit list"

text   Values. We include a type identifier, tyid, in the literal for constructors
  make typing and well-formedness checking easier


nominal_datatype "v" = 
  V_lit "l"        ( [ _ ]v)
  | V_var "x"        ( [ _ ]v)
  | V_pair "v" "v"   ( [ _ , _ ]v)
  | V_cons tyid dc "v" 
  | V_consp tyid dc b "v" 

text  Binary Operations
nominal_datatype "opp" = Plus ( plus) | LEq (leq) | Eq (eq)

text  Expressions
nominal_datatype "e" = 
  AE_val "v"           ( [ _ ]e       )
  | AE_app "f" "v"       ( [ _ ( _ ) ]e )
  | AE_appP  "f" "b" "v" ( [_ [ _ ] ( _ )]e )
  | AE_op "opp" "v" "v"  ( [ _ _ _ ]e  )
  | AE_concat v v        ( [ _ @@ _ ]e )
  | AE_fst "v"           ( [#1_ ]e    )
  | AE_snd "v"           ( [#2_ ]e     )
  | AE_mvar "u"          ( [ _ ]e      )
  | AE_len "v"           ( [| _ |]e    )
  | AE_split "v" "v"     ( [ _ / _ ]e  )

text  Expressions for constraints
nominal_datatype "ce" = 
  CE_val "v"           ( [ _ ]ce      )
  | CE_op "opp" "ce" "ce"  ( [ _ _ _ ]ce  )
  | CE_concat ce ce        ( [ _ @@ _ ]ce )
  | CE_fst "ce"           ( [#1_]ce      )
  | CE_snd "ce"           ( [#2_]ce      )
  | CE_len "ce"           ( [| _ |]ce    )

text   Constraints
nominal_datatype "c" = 
  C_true          ( TRUE [] 50 )
  | C_false         ( FALSE [] 50 )
  | C_conj "c" "c"  (_ AND _ [505050
  | C_disj "c" "c"  (_ OR _ [50,5050)
  | C_not "c"       ( ¬ _ [] 50 )
  | C_imp "c" "c"   (_ IMP _ [505050
  | C_eq "ce" "ce"  (_ == _ [505050

text   Refined types
nominal_datatype "τ" = 
  T_refined_type  x::x b c::c   binds x in c   ({ _ : _ | _ } [50501000)

text  Statements

nominal_datatype 
  s = 
  AS_val v                             ( [_]s)                  
  | AS_let x::x  e s::s binds x in s     ( (LET _ = _ IN _))
  | AS_let2 x::x τ  s s::s binds x in s  ( (LET _ : _ = _ IN _))
  | AS_if v s s                          ( (IF _ THEN _ ELSE _) [061061)
  | AS_var u::u τ v s::s  binds u in s   ( (VAR _ : _ = _ IN _))
  | AS_assign u  v                       ( (_ ::= _))
  | AS_match v branch_list               ( (MATCH _ WITH { _ }))
  | AS_while s s                         ( (WHILE _ DO { _ } ) [0061)     
  | AS_seq s s                           ( ( _ ;; _ )  [10006161)
  | AS_assert c s                        ( (ASSERT _ IN _ ) )
    and branch_s = 
    AS_branch dc x::x s::s binds x in s  ( ( _ _ ==> _ ))   
    and branch_list = 
    AS_final  branch_s                   ( { _ } )
  | AS_cons  branch_s branch_list        ( ( _ | _ ))

text  Function and union type definitions

nominal_datatype "fun_typ"  =
  AF_fun_typ x::x "b" c::c τ::τ s::s binds x in c τ s

nominal_datatype "fun_typ_q" = 
  AF_fun_typ_some bv::bv ft::fun_typ binds bv in ft
  | AF_fun_typ_none fun_typ

nominal_datatype "fun_def" =  AF_fundef f fun_typ_q 

nominal_datatype "type_def" = 
  AF_typedef string "(string * τ) list"
  |  AF_typedef_poly string bv::bv dclist::"(string * τ) list"  binds bv in dclist

lemma check_typedef_poly:
  "AF_typedef_poly ''option'' bv [ (''None'', { zz : B_unit | TRUE }), (''Some'', { zz : B_var bv | TRUE }) ] =
    AF_typedef_poly ''option'' bv2 [ (''None'', { zz : B_unit | TRUE }), (''Some'', { zz : B_var bv2 | TRUE }) ]"
  by auto

nominal_datatype "var_def" =  AV_def u τ v

text   Programs
nominal_datatype "p" = 
  AP_prog "type_def list" "fun_def list" "var_def list" "s" (PROG _ _ _ _)

declare l.supp [simp] v.supp [simp]  e.supp [simp] s_branch_s_branch_list.supp [simp]  τ.supp [simp] c.supp [simp] b.supp[simp]

subsection Lemmas

text These lemmas deal primarily with freshness and alpha-equivalence

subsubsection Atoms

lemma x_not_in_u_atoms[simp]:
  fixes u::u and x::x and us::"u set"
  shows "atom x atom`us"
  by (simp add: image_iff)

lemma x_fresh_u[simp]:
  fixes u::u and x::x
  shows "atom x u"
  by auto

lemma x_not_in_b_set[simp]:
  fixes  x::x and bs::"bv fset"
  shows "atom x supp bs"
  by(induct bs,auto, simp add: supp_finsert supp_at_base)

lemma x_fresh_b[simp]:
  fixes  x::x and b::b
  shows "atom x b"
  apply (induct b rule: b.induct, auto simp: pure_supp)
  using pure_supp fresh_def by blast+

lemma x_fresh_bv[simp]:
  fixes  x::x and bv::bv
  shows "atom x bv"
  using fresh_def supp_at_base by auto

lemma u_not_in_x_atoms[simp]:
  fixes u::u and x::x and xs::"x set"
  shows "atom u atom`xs"
  by (simp add: image_iff)

lemma bv_not_in_x_atoms[simp]:
  fixes bv::bv and x::x and xs::"x set"
  shows "atom bv atom`xs"
  by (simp add: image_iff)

lemma u_not_in_b_atoms[simp]:
  fixes b :: b and u::u
  shows "atom u supp b"
  by (induct b rule: b.induct,auto simp: pure_supp supp_at_base)

lemma u_not_in_b_set[simp]:
  fixes  u::u and bs::"bv fset"
  shows "atom u supp bs"
  by(induct bs, auto simp add: supp_at_base supp_finsert)

lemma u_fresh_b[simp]:
  fixes  x::u and b::b
  shows "atom x b"
  by(induct b rule: b.induct, auto simp: pure_fresh )

lemma supp_b_v_disjoint:
  fixes x::x and bv::bv
  shows "supp (V_var x) supp (B_var bv) = {}" 
  by (simp add: supp_at_base)

lemma supp_b_u_disjoint[simp]:
  fixes b::b and u::u
  shows "supp u supp b = {}" 
  by(nominal_induct b rule:b.strong_induct,(auto simp add: pure_supp b.supp supp_at_base)+)

lemma u_fresh_bv[simp]:
  fixes  u::u and b::bv
  shows "atom u b"
  using fresh_at_base by simp

subsubsection Basic Types

nominal_function b_of :: ==> b" where
  "b_of { z : b | c } = b"
     apply(auto,simp add: eqvt_def b_of_graph_aux_def )
  by (meson τ.exhaust)
nominal_termination (eqvt)  by lexicographic_order

lemma supp_b_empty[simp]:
  fixes b :: b and x::x
  shows "atom x supp b"
  by (induct b rule: b.induct, auto simp: pure_supp supp_at_base x_not_in_b_set)

lemma flip_b_id[simp]:
  fixes x::x and b::b
  shows "(x x') b = b"
  by(rule flip_fresh_fresh, auto simp add: fresh_def)

lemma flip_x_b_cancel[simp]:
  fixes x::x and y::x  and b::b and bv::bv
  shows "(x y) b = b" and "(x y) bv = bv"
  using flip_b_id  apply simp
  by (metis b.eq_iff(7) b.perm_simps(7) flip_b_id)

lemma flip_bv_x_cancel[simp]:
  fixes bv::bv and z::bv and x::x
  shows "(bv z) x = x" using flip_fresh_fresh[of bv x z] fresh_at_base by auto

lemma flip_bv_u_cancel[simp]:
  fixes bv::bv and z::bv and x::u
  shows "(bv z) x = x" using flip_fresh_fresh[of bv x z] fresh_at_base by auto

subsubsection Literals

lemma supp_bitvec_empty:
  fixes bv::"bit list"
  shows "supp bv = {}"
proof(induct bv)
  case Nil
  then show ?case using supp_Nil by auto
next
  case (Cons a bv)
  then show ?case using supp_Cons  bit.supp
    by (metis (mono_tags, opaque_lifting) bit.strong_exhaust l.supp(5) sup_bot.right_neutral)
qed

lemma bitvec_pure[simp]:
  fixes bv::"bit list" and x::x
  shows "atom x bv" using fresh_def supp_bitvec_empty by auto

lemma supp_l_empty[simp]:
  fixes l:: l
  shows "supp (V_lit l) = {}"
  by(nominal_induct l rule: l.strong_induct,
      auto simp add: l.strong_exhaust pure_supp v.fv_defs supp_bitvec_empty)

lemma type_l_nosupp[simp]:
  fixes x::x and l::l
  shows "atom x supp ({ z : b | [[z]v]ce == [[l]v]ce })"
  using supp_at_base supp_l_empty ce.supp(1) c.supp τ.supp by force

lemma flip_bitvec0:
  fixes x::"bit list"
  assumes "atom c (z, x, z')"
  shows "(z c) x = (z' c) x"
proof - 
  have "atom z x" and "atom z' x"
    using flip_fresh_fresh assms supp_bitvec_empty fresh_def by blast+
  moreover have "atom c x" using  supp_bitvec_empty fresh_def by auto
  ultimately show ?thesis  using assms flip_fresh_fresh by metis
qed

lemma flip_bitvec:
  assumes "atom c (z, L_bitvec x, z')"
  shows "(z c) x = (z' c) x"
proof - 
  have "atom z x" and "atom z' x"
    using flip_fresh_fresh assms supp_bitvec_empty fresh_def by blast+
  moreover have "atom c x" using  supp_bitvec_empty fresh_def by auto
  ultimately show ?thesis  using assms flip_fresh_fresh by metis
qed

lemma type_l_eq:
  shows "{ z : b | [[z]v]ce == [V_lit l]ce } = ({ z' : b | [[z']v]ce == [V_lit l]ce })"
  by(auto,nominal_induct l rule: l.strong_induct,auto, metis permute_pure, auto simp add: flip_bitvec)

lemma flip_l_eq:
  fixes x::l
  shows "(z c) x = (z' c) x"
proof - 
  have "atom z x" and "atom c x" and "atom z' x"
    using flip_fresh_fresh fresh_def supp_l_empty by fastforce+
  thus ?thesis using flip_fresh_fresh by metis
qed

lemma flip_l_eq1:
  fixes x::l
  assumes  "(z c) x = (z' c) x'"
  shows "x' = x"
proof - 
  have "atom z x" and "atom c x'" and "atom c x" and "atom z' x'"
    using flip_fresh_fresh fresh_def supp_l_empty by fastforce+
  thus ?thesis using flip_fresh_fresh assms by metis
qed

subsubsection Types

lemma flip_base_eq:
  fixes b::b and x::x and y::x                      
  shows "(x y) b = b"
  using b.fresh  by (simp add: flip_fresh_fresh fresh_def)

text  Obtain an alpha-equivalent type where the bound variable is fresh in some term t
lemma has_fresh_z0:
  fixes t::"'b::fs"
  shows "z. atom z (c',t) ({z' : b | c' }) = ({ z : b | (z z' ) c' })"
proof -
  obtain z::x where fr: "atom z (c',t)" using obtain_fresh by blast
  moreover hence "({ z' : b | c' }) = ({ z : b | (z z') c' })"  
    using τ.eq_iff Abs1_eq_iff
    by (metis flip_commute flip_fresh_fresh fresh_PairD(1))
  ultimately show ?thesis by fastforce
qed

lemma has_fresh_z:
  fixes t::"'b::fs"
  shows "z b c. atom z t τ = { z : b | c }"
proof -
  obtain z' and b and c' where teq: "τ = ({ z' : b | c' })" using τ.exhaust by blast
  obtain z::x where fr: "atom z (t,c')" using obtain_fresh by blast
  hence "({ z' : b | c' }) = ({ z : b | (z z') c' })"  using τ.eq_iff Abs1_eq_iff
      flip_commute flip_fresh_fresh fresh_PairD(1)  by (metis fresh_PairD(2))
  hence "atom z t τ = ({ z : b | (z z') c' })" using fr teq by force
  thus ?thesis using teq fr by fast
qed

lemma obtain_fresh_z:
  fixes t::"'b::fs"
  obtains z and b and c where "atom z t τ = { z : b | c }"
  using has_fresh_z by blast

lemma has_fresh_z2:
  fixes t::"'b::fs"
  shows "z c. atom z t τ = { z : b_of τ | c }" 
proof -
  obtain z and b and c where "atom z t τ = { z : b | c }" using obtain_fresh_z by metis
  moreover then have "b_of τ = b" using τ.eq_iff by simp
  ultimately show ?thesis using obtain_fresh_z τ.eq_iff by auto
qed

lemma obtain_fresh_z2:
  fixes t::"'b::fs"
  obtains z and  c where "atom z t τ = { z : b_of τ | c }"
  using has_fresh_z2 by blast

subsubsection Values

lemma u_notin_supp_v[simp]:
  fixes u::u and v::v
  shows "atom u supp v" 
proof(nominal_induct v rule: v.strong_induct)
  case (V_lit l)
  then show ?case  using supp_l_empty by auto
next
  case (V_var x)
  then show ?case 
    by (simp add: supp_at_base)
next
  case (V_pair v1 v2)
  then show ?case by auto
next
  case (V_cons tyid list v)
  then show ?case using pure_supp by auto
next
  case (V_consp tyid list b v)
  then show ?case using pure_supp by auto
qed

lemma u_fresh_xv[simp]:
  fixes u::u and x::x and v::v
  shows "atom u (x,v)"
proof - 
  have "atom u x" using fresh_def by fastforce
  moreover have "atom u v" using fresh_def u_notin_supp_v by metis
  ultimately show ?thesis using fresh_prod2 by auto
qed

text  Part of an effort to make the proofs across inductive cases more uniform by distilling
  non-uniform parts into lemmas like this

lemma v_flip_eq:
  fixes v::v and va::v and x::x and c::x
  assumes "atom c (v, va)" and "atom c (x, xa, v, va)" and "(x c) v = (xa c) va" 
  shows "((v = V_lit l (l'. va = V_lit l' (x c) l = (xa c) l')))
         ((v = V_var y (y'. va = V_var y' (x c) y = (xa c) y')))
         ((v = V_pair vone vtwo (v1' v2'. va = V_pair v1' v2' (x c) vone = (xa c) v1' (x c) vtwo = (xa c) v2')))
         ((v = V_cons tyid dc vone (v1'. va = V_cons tyid dc v1' (x c) vone = (xa c) v1')))
         ((v = V_consp tyid dc b vone (v1'. va = V_consp tyid dc b v1' (x c) vone = (xa c) v1')))" 
  using assms proof(nominal_induct v rule:v.strong_induct)
  case (V_lit l)
  then show ?case  using assms v.perm_simps 
      empty_iff flip_def fresh_def fresh_permute_iff supp_l_empty swap_fresh_fresh v.fresh 
    by (metis permute_swap_cancel2 v.distinct)
next
  case (V_var x)
  then show ?case  using assms v.perm_simps 
      empty_iff flip_def fresh_def fresh_permute_iff supp_l_empty swap_fresh_fresh v.fresh 
    by (metis permute_swap_cancel2 v.distinct)
next
  case (V_pair v1 v2)
  have " (V_pair v1 v2 = V_pair vone vtwo (v1' v2'. va = V_pair v1' v2' (x c) vone = (xa c) v1' (x c) vtwo = (xa c) v2'))" proof
    assume "V_pair v1 v2= V_pair vone vtwo"    
    thus  "(v1' v2'. va = V_pair v1' v2' (x c) vone = (xa c) v1' (x c) vtwo = (xa c) v2')"
      using V_pair assms 
      by (metis (no_types, opaque_lifting) flip_def permute_swap_cancel v.perm_simps(3)) 
  qed
  thus ?case using V_pair by auto
next
  case (V_cons tyid dc v1)
  have " (V_cons tyid dc v1 = V_cons tyid dc vone ( v1'. va = V_cons tyid dc v1' (x c) vone = (xa c) v1'))" proof
    assume as: "V_cons tyid dc v1 = V_cons tyid dc vone"    
    hence "(x c) (V_cons tyid dc vone) = V_cons tyid dc ((x c) vone)" proof -
      have "(x c) dc = dc" using pure_permute_id  by metis
      moreover have "(x c) tyid = tyid" using pure_permute_id  by metis
      ultimately show ?thesis using v.perm_simps(4by simp
    qed
    then obtain v1' where "(xa c) va = V_cons tyid dc v1' (x c) vone = v1'" using assms V_cons
      using as by fastforce
    hence " va = V_cons tyid dc ((xa c) v1') (x c) vone = v1'" using permute_flip_cancel empty_iff flip_def fresh_def supp_b_empty swap_fresh_fresh
      by (metis pure_fresh v.perm_simps(4))

    thus  "(v1'. va = V_cons tyid dc v1' (x c) vone = (xa c) v1')"
      using V_cons assms by simp     
  qed
  thus ?case using V_cons by auto
next
  case (V_consp tyid dc b v1)
  have " (V_consp tyid dc b v1 = V_consp tyid dc b vone ( v1'. va = V_consp tyid dc b v1' (x c) vone = (xa c) v1'))" proof
    assume as: "V_consp tyid dc b v1 = V_consp tyid dc b vone"    
    hence "(x c) (V_consp tyid dc b vone) = V_consp tyid dc b ((x c) vone)" proof -
      have "(x c) dc = dc" using pure_permute_id  by metis
      moreover have "(x c) tyid = tyid" using pure_permute_id  by metis
      ultimately show ?thesis using v.perm_simps(4by simp
    qed
    then obtain v1' where "(xa c) va = V_consp tyid dc b v1' (x c) vone = v1'" using assms V_consp
      using as by fastforce
    hence " va = V_consp tyid dc b ((xa c) v1') (x c) vone = v1'" using permute_flip_cancel empty_iff flip_def fresh_def supp_b_empty swap_fresh_fresh
        pure_fresh v.perm_simps 
      by (metis (mono_tags, opaque_lifting))   
    thus   "(v1'. va = V_consp tyid dc b v1' (x c) vone = (xa c) v1')"
      using V_consp assms by simp     
  qed
  thus ?case using V_consp by auto
qed

lemma flip_eq:
  fixes x::x and xa::x and s::"'a::fs" and sa::"'a::fs"
  assumes "(c. atom c (s, sa) atom c (x, xa, s, sa) (x c) s = (xa c) sa)" and "x xa"
  shows "(x xa) s = sa" 
proof - 
  have  " ([[atom x]]lst. s = [[atom xa]]lst. sa)" using assms Abs1_eq_iff_all by simp
  hence  "(xa = x sa = s xa x sa = (xa x) s atom xa s)" using assms Abs1_eq_iff[of xa sa x s] by simp
  thus ?thesis using assms
    by (metis flip_commute)
qed

lemma  swap_v_supp:
  fixes v::v and d::x and z::x
  assumes "atom d v"
  shows "supp ((z d ) v) supp v - { atom z } { atom d}"
  using assms
proof(nominal_induct v rule:v.strong_induct)
  case (V_lit l)
  then show ?case using l.supp by (metis supp_l_empty empty_subsetI l.strong_exhaust pure_supp supp_eqvt v.supp)
next
  case (V_var x)
  hence "d x" using fresh_def by fastforce
  thus ?case apply(cases "z = x")  using   supp_at_base V_var dx by fastforce+
next
  case (V_cons tyid dc v)
  show ?case using v.supp(4) pure_supp 
    using V_cons.hyps V_cons.prems fresh_def by auto
next
  case (V_consp tyid dc b v)
  show ?case using v.supp(4) pure_supp 
    using V_consp.hyps V_consp.prems fresh_def by auto
qed(force+)

subsubsection Expressions

lemma  swap_e_supp:
  fixes e::e and d::x and z::x
  assumes "atom d e"
  shows "supp ((z d ) e) supp e - { atom z } { atom d}"
  using assms
proof(nominal_induct e rule:e.strong_induct)
  case (AE_val v)
  then show ?case using swap_v_supp by simp
next
  case (AE_app f v)
  then show ?case using swap_v_supp  by (simp add: pure_supp)
next
  case (AE_appP b f v)
  hence df: "atom d v" using fresh_def e.supp by force
  have  "supp ((z d ) (AE_appP b f v)) = supp (AE_appP b f ((z d ) v))" using  e.supp 
    by (metis b.eq_iff(3) b.perm_simps(3) e.perm_simps(3) flip_b_id)
  also have "... = supp b supp f supp ((z d ) v)" using e.supp by auto
  also have "... supp b supp f supp v - { atom z } { atom d}" using swap_v_supp[OF df] pure_supp  by auto
  finally show ?case using e.supp by auto
next
  case (AE_op opp v1 v2)
  hence df: "atom d v1 atom d v2" using fresh_def e.supp by force
  have "((z d ) (AE_op opp v1 v2)) = AE_op opp ((z d ) v1) ((z d ) v2)" using
      e.perm_simps flip_commute opp.perm_simps AE_op opp.strong_exhaust  pure_supp
    by (metis (full_types))

  hence "supp ((z d) AE_op opp v1 v2) = supp (AE_op opp ((z d) v1) ((z d) v2))" by simp
  also have "... = supp ((z d) v1) supp ((z d) v2)" using e.supp 
    by (metis (mono_tags, opaque_lifting) opp.strong_exhaust opp.supp sup_bot.left_neutral)
  also have "... (supp v1 - { atom z } { atom d}) (supp v2 - { atom z } { atom d})" using swap_v_supp AE_op df by blast
  finally show ?case using e.supp opp.supp by blast
next
  case (AE_fst v)
  then show ?case   using swap_v_supp by auto
next
  case (AE_snd v)
  then show ?case   using swap_v_supp by auto
next
  case (AE_mvar u)
  then show ?case using 
      Diff_empty Diff_insert0 Un_upper1 atom_x_sort flip_def flip_fresh_fresh fresh_def set_eq_subset supp_eqvt swap_set_in_eq 
    by (metis sort_of_atom_eq)
next 
  case (AE_len v)
  then show ?case   using swap_v_supp by auto
next
  case (AE_concat v1 v2)
  then show ?case   using swap_v_supp by auto
next
  case (AE_split v1 v2)
  then show ?case   using swap_v_supp by auto
qed

lemma  swap_ce_supp:
  fixes e::ce and d::x and z::x
  assumes "atom d e"
  shows "supp ((z d ) e) supp e - { atom z } { atom d}"
  using assms
proof(nominal_induct e rule:ce.strong_induct)
  case (CE_val v)
  then show ?case using swap_v_supp ce.fresh ce.supp by simp
next
  case (CE_op opp v1 v2)
  hence df: "atom d v1 atom d v2" using fresh_def e.supp by force
  have "((z d ) (CE_op opp v1 v2)) = CE_op opp ((z d ) v1) ((z d ) v2)" using
      ce.perm_simps flip_commute opp.perm_simps CE_op opp.strong_exhaust x_fresh_b pure_supp 
    by (metis (full_types))

  hence "supp ((z d) CE_op opp v1 v2) = supp (CE_op opp ((z d) v1) ((z d) v2))" by simp
  also have "... = supp ((z d) v1) supp ((z d) v2)" using ce.supp 
    by (metis (mono_tags, opaque_lifting) opp.strong_exhaust opp.supp sup_bot.left_neutral)
  also have "... (supp v1 - { atom z } { atom d}) (supp v2 - { atom z } { atom d})" using swap_v_supp CE_op df by blast
  finally show ?case using ce.supp opp.supp by blast
next
  case (CE_fst v)
  then show ?case   using ce.supp ce.fresh swap_v_supp by auto
next
  case (CE_snd v)
  then show ?case   using ce.supp ce.fresh swap_v_supp by auto
next
  case (CE_len v)
  then show ?case   using ce.supp ce.fresh swap_v_supp by auto
next
  case (CE_concat v1 v2)
  then show ?case using ce.supp ce.fresh swap_v_supp ce.perm_simps 
  proof -
    have "x v xa. ¬ atom (x::x) (v::v) supp ((xa x) v) supp v - {atom xa} {atom x}"
      by (meson swap_v_supp) (* 0.0 ms *)
    then show ?thesis
      using CE_concat ce.supp by auto
  qed
qed

lemma  swap_c_supp:
  fixes c::c and d::x and z::x
  assumes "atom d c"
  shows "supp ((z d ) c) supp c - { atom z } { atom d}"
  using assms
proof(nominal_induct c rule:c.strong_induct)
  case (C_eq e1 e2)
  then show ?case using swap_ce_supp by auto
qed(auto+)

lemma type_e_eq:
  assumes "atom z e" and "atom z' e"
  shows "{ z : b | [[z]v]ce == e } = ({ z' : b | [[z']v]ce == e })"
  by (auto,metis (full_types) assms(1) assms(2) flip_fresh_fresh fresh_PairD(1) fresh_PairD(2))

lemma type_e_eq2:
  assumes "atom z e" and "atom z' e" and "b=b'"
  shows "{ z : b | [[z]v]ce == e } = ({ z' : b' | [[z']v]ce == e })"
  using assms type_e_eq by fast

lemma e_flip_eq:
  fixes e::e and ea::e
  assumes "atom c (e, ea)" and "atom c (x, xa, e, ea)" and "(x c) e = (xa c) ea" 
  shows "(e = AE_val w (w'. ea = AE_val w' (x c) w = (xa c) w'))
         (e = AE_op opp v1 v2 (v1' v2'. ea = AS_op opp v1' v2' (x c) v1 = (xa c) v1') (x c) v2 = (xa c) v2')
         (e = AE_fst v (v'. ea = AE_fst v' (x c) v = (xa c) v'))
         (e = AE_snd v (v'. ea = AE_snd v' (x c) v = (xa c) v'))
         (e = AE_len v (v'. ea = AE_len v' (x c) v = (xa c) v'))
         (e = AE_concat v1 v2 (v1' v2'. ea = AS_concat v1' v2' (x c) v1 = (xa c) v1') (x c) v2 = (xa c) v2')
         (e = AE_app f v (v'. ea = AE_app f v' (x c) v = (xa c) v'))"
  by (metis assms e.perm_simps permute_flip_cancel2)

lemma fresh_opp_all:
  fixes opp::opp
  shows "z opp"
  using e.fresh opp.exhaust opp.fresh  by metis

lemma fresh_e_opp_all:
  shows "(z v1 z v2) = z AE_op opp v1 v2"
  using e.fresh opp.exhaust opp.fresh fresh_opp_all by simp

lemma fresh_e_opp:
  fixes z::x
  assumes "atom z v1 atom z v2"
  shows "atom z AE_op opp v1 v2"
  using e.fresh opp.exhaust opp.fresh opp.supp  by (metis assms)

subsubsection Statements

lemma branch_s_flip_eq:
  fixes v::v and va::v
  assumes "atom c (v, va)" and "atom c (x, xa, v, va)" and "(x c) s = (xa c) sa" 
  shows "(s = AS_val w (w'. sa = AS_val w' (x c) w = (xa c) w'))
         (s = AS_seq s1 s2 (s1' s2'. sa = AS_seq s1' s2' (x c) s1 = (xa c) s1') (x c) s2 = (xa c) s2')
         (s = AS_if v s1 s2 (v' s1' s2'. sa = AS_if seq s1' s2' (x c) s1 = (xa c) s1') (x c) s2 = (xa c) s2' (x c) c = (xa c) v')"
  by (metis assms s_branch_s_branch_list.perm_simps permute_flip_cancel2)

section Context Syntax

subsection Datatypes

text Type and function/type definition contexts
type_synonym Φ = "fun_def list"
type_synonym Θ = "type_def list"
type_synonym B = "bv fset"

datatype Γ = 
  GNil
  | GCons "x*b*c" Γ  (infixr #\Γ 65)

datatype Δ = 
  DNil  ([]\Δ)
  | DCons "u*τ" Δ  (infixr #\Δ 65)

subsection Functions and Lemmas

lemma Γ_induct [case_names GNil GCons] : "P GNil ==> (x b c Γ'. P Γ' ==> P ((x,b,c) #\<Gamma> Γ')) ==> P Γ"
proof(induct Γ rule:Γ.induct)
  case GNil
  then show ?case by auto 
next
  case (GCons x1 x2)
  then obtain x and b and c where "x1=(x,b,c)"  using prod_cases3 by blast
  then show ?case using GCons by presburger
qed

instantiation Δ ::  pt
begin

primrec permute_Δ
  where
    DNil_eqvt:  "p DNil = DNil"
  | DCons_eqvt: "p (x #\<Delta> xs) = p x #\<Delta> p (xs::Δ)"

instance  by standard (induct_tac [!] x, simp_all)
end

lemmas [eqvt] =  permute_Δ.simps 

lemma Δ_induct [case_names DNil DCons] : "P DNil ==> (u t Δ'. P Δ' ==> P ((u,t) #\<Delta> Δ')) ==> P Δ"
proof(induct Δ rule: Δ.induct)
  case DNil
  then show ?case by auto 
next
  case (DCons x1 x2)
  then obtain u and t  where "x1=(u,t)"  by fastforce
  then show ?case using DCons by presburger
qed

lemma Φ_induct [case_names PNil PConsNone PConsSome] : "P [] ==> (f x b c τ s' Φ'. P Φ' ==> P ((AF_fundef f (AF_fun_typ_none (AF_fun_typ x b c τ s'))) # Φ')) ==>
                                                                  (f bv x b c τ s' Φ'. P Φ' ==> P ((AF_fundef f (AF_fun_typ_some bv (AF_fun_typ x b c τ s'))) # Φ')) ==> P Φ"
proof(induct Φ rule: list.induct)
  case Nil
  then show ?case by auto 
next
  case (Cons x1 x2)
  then obtain f and t where ft: "x1 = (AF_fundef f t)" 
    by (meson fun_def.exhaust)
  then show ?case proof(nominal_induct t rule:fun_typ_q.strong_induct)
    case (AF_fun_typ_some bv ft)
    then show ?case using Cons ft 
      by (metis fun_typ.exhaust)
  next
    case (AF_fun_typ_none ft)
    then show ?case using Cons ft 
      by (metis fun_typ.exhaust)
  qed
qed

lemma Θ_induct [case_names TNil AF_typedef AF_typedef_poly] : "P [] ==> (tid dclist Θ'. P Θ' ==> P ((AF_typedef tid dclist) # Θ')) ==>
                                                                  (tid bv dclist Θ'. P Θ' ==> P ((AF_typedef_poly tid bv dclist ) # Θ')) ==> P Θ"
proof(induct Θ rule: list.induct)
  case Nil
  then show ?case by auto
next
  case (Cons td T)
  show ?case by(cases td rule: type_def.exhaust, (simp add: Cons)+)
qed

instantiation Γ ::  pt
begin

primrec permute_Γ
  where
    GNil_eqvt:  "p GNil = GNil"
  | GCons_eqvt: "p (x #\<Gamma> xs) = p x #\<Gamma> p (xs::Γ)"

instance by standard (induct_tac [!] x, simp_all)
end

lemmas [eqvt] =  permute_Γ.simps 

lemma G_cons_eqvt[simp]:
  fixes Γ::Γ
  shows "p ((x,b,c) #\<Gamma> Γ) = ((p x, p b , p c) #\<Gamma> (p Γ ))" (is "?A = ?B" )
  using Cons_eqvt triple_eqvt  supp_b_empty by simp

lemma G_cons_flip[simp]:
  fixes  x::x and Γ::Γ
  shows  "(xx') ((x'',b,c) #\<Gamma> Γ) = (((xx') x'', b , (xx') c) #\<Gamma> ((xx') Γ ))" 
  using Cons_eqvt triple_eqvt  supp_b_empty by auto

lemma G_cons_flip_fresh[simp]:
  fixes  x::x and Γ::Γ 
  assumes  "atom x (c,Γ)" and "atom x' (c,Γ)" 
  shows  "(xx') ((x',b,c) #\<Gamma> Γ) = ((x, b , c) #\<Gamma> Γ )" 
  using G_cons_flip flip_fresh_fresh assms by force

lemma G_cons_flip_fresh2[simp]:
  fixes  x::x and Γ::Γ 
  assumes  "atom x (c,Γ)" and "atom x' (c,Γ)" 
  shows  "(xx') ((x,b,c) #\<Gamma> Γ) = ((x', b , c) #\<Gamma> Γ )" 
  using G_cons_flip flip_fresh_fresh assms by force

lemma G_cons_flip_fresh3[simp]:
  fixes  x::x and Γ::Γ 
  assumes  "atom x Γ" and "atom x' Γ" 
  shows  "(xx') ((x',b,c) #\<Gamma> Γ) = ((x, b , (xx') c) #\<Gamma> Γ )" 
  using G_cons_flip flip_fresh_fresh assms by force

lemma neq_GNil_conv: "(xs GNil) = (y ys. xs = y #\<Gamma> ys)"
  by (induct xs) auto

nominal_function toList :: ==> (x*b*c) list" where
  "toList GNil = []"
"toList (GCons xbc G) = xbc#(toList G)"
       apply (auto, simp add: eqvt_def toList_graph_aux_def )
  using neq_GNil_conv surj_pair by metis
nominal_termination (eqvt)
  by lexicographic_order

nominal_function toSet :: ==> (x*b*c) set" where
  "toSet GNil = {}"
"toSet (GCons xbc G) = {xbc} (toSet G)"
       apply (auto,simp add: eqvt_def toSet_graph_aux_def )
  using neq_GNil_conv surj_pair by metis
nominal_termination (eqvt)
  by lexicographic_order

nominal_function append_g :: ==> Γ ==> Γ" (infixr @ 65where
  "append_g GNil g = g"
"append_g (xbc #\<Gamma> g1) g2 = (xbc #\<Gamma> (g1@g2))"
       apply (auto,simp add: eqvt_def append_g_graph_aux_def )
  using neq_GNil_conv surj_pair by metis
nominal_termination (eqvt) by lexicographic_order

nominal_function dom  ::  ==> x set"  where
  "dom Γ = (fst` (toSet Γ))"
     apply auto
  unfolding  eqvt_def dom_graph_aux_def lfp_eqvt toSet.eqvt by simp
nominal_termination (eqvt) by lexicographic_order

text  Use of this is sometimes mixed in with use of freshness and support for the context however it makes it clear
  for immutable variables, the context is `self-supporting'


nominal_function atom_dom  ::  ==> atom set"  where
  "atom_dom Γ = atom`(dom Γ)"
     apply auto
  unfolding  eqvt_def atom_dom_graph_aux_def lfp_eqvt toSet.eqvt by simp
nominal_termination (eqvt) by lexicographic_order

subsection Immutable Variable Context Lemmas

lemma append_GNil[simp]:
  "GNil @ G = G"
  by simp

lemma append_g_toSetU [simp]: "toSet (G1@G2) = toSet G1 toSet G2"
  by(induct G1, auto+)

lemma supp_GNil: 
  shows "supp GNil = {}"
  by (simp add: supp_def)

lemma supp_GCons: 
  fixes xs::Γ
  shows "supp (x #\<Gamma> xs) = supp x supp xs"
  by (simp add: supp_def Collect_imp_eq Collect_neg_eq)

lemma atom_dom_eq[simp]: 
  fixes G::Γ
  shows  "atom_dom ((x, b, c) #\<Gamma> G) = atom_dom ((x, b, c') #\<Gamma> G)" 
  using atom_dom.simps toSet.simps by simp

lemma dom_append[simp]:
  "atom_dom (Γ@Γ') = atom_dom Γ atom_dom Γ'"
  using image_Un append_g_toSetU atom_dom.simps dom.simps by metis

lemma dom_cons[simp]:
  "atom_dom ((x,b,c) #\<Gamma> G) = { atom x } atom_dom G"
  using image_Un append_g_toSetU atom_dom.simps by auto

lemma fresh_GNil[ms_fresh]: 
  shows "a GNil"
  by (simp add: fresh_def supp_GNil)

lemma fresh_GCons[ms_fresh]: 
  fixes xs::Γ
  shows "a (x #\<Gamma> xs) a x a xs"
  by (simp add: fresh_def supp_GCons)

lemma dom_supp_g[simp]:
  "atom_dom G supp G"
  apply(induct G rule: Γ_induct,simp)
  using supp_at_base supp_Pair atom_dom.simps supp_GCons by fastforce

lemma fresh_append_g[ms_fresh]:
  fixes xs::Γ
  shows "a (xs @ ys) a xs a ys"
  by (induct xs) (simp_all add: fresh_GNil fresh_GCons)

lemma append_g_assoc:
  fixes xs::Γ 
  shows  "(xs @ ys) @ zs = xs @ (ys @ zs)"
  by (induct xs) simp_all

lemma append_g_inside:
  fixes xs::Γ 
  shows "xs @ (x #\<Gamma> ys) = (xs @ (x #\<Gamma> GNil)) @ ys"
  by(induct xs,auto+)

lemma finite_Γ:
  "finite (toSet Γ)" 
  by(induct Γ rule: Γ_induct,auto)

lemma supp_Γ:
  "supp Γ = supp (toSet Γ)"
proof(induct Γ rule: Γ_induct)
  case GNil
  then show ?case using supp_GNil toSet.simps
    by (simp add: supp_set_empty)
next
  case (GCons x b c Γ')
  then show ?case using  supp_GCons toSet.simps finite_Γ supp_of_finite_union 
    using supp_of_finite_insert by fastforce
qed

lemma supp_of_subset:
  fixes G::"('a::fs set)"
  assumes "finite G" and "finite G'" and "G G'" 
  shows "supp G supp G'"
  using supp_of_finite_sets assms  by (metis subset_Un_eq supp_of_finite_union)

lemma supp_weakening:
  assumes "toSet G toSet G'"
  shows "supp G supp G'"
  using supp_Γ finite_Γ by (simp add: supp_of_subset assms)

lemma fresh_weakening[ms_fresh]:
  assumes "toSet G toSet G'" and "x G'" 
  shows "x G"
proof(rule ccontr)
  assume "¬ x G"
  hence "x supp G" using fresh_def by auto
  hence "x supp G'" using supp_weakening assms by auto
  thus False using fresh_def assms by auto
qed

instance Γ :: fs
  by (standard, induct_tac x, simp_all add: supp_GNil supp_GCons  finite_supp)

lemma fresh_gamma_elem:
  fixes Γ::Γ
  assumes "a Γ"
    and "e toSet Γ"
  shows "a e"
  using assms by(induct Γ,auto simp add: fresh_GCons)

lemma fresh_gamma_append:
  fixes xs::Γ
  shows "a (xs @ ys) a xs a ys"
  by (induct xs, simp_all add: fresh_GNil fresh_GCons)

lemma supp_triple[simp]:
  shows "supp (x, y, z) = supp x supp y supp z"
proof -
  have "supp (x,y,z) = supp (x,(y,z))"  by auto
  hence "supp (x,y,z) = supp x (supp y supp z)" using supp_Pair by metis
  thus ?thesis by auto
qed

lemma supp_append_g:
  fixes xs::Γ
  shows "supp (xs @ ys) = supp xs supp ys"
  by(induct xs,auto simp add: supp_GNil supp_GCons )

lemma fresh_in_g[simp]:
  fixes Γ::Γ and x'::x
  shows "atom x' Γ' @ (x, b0, c0) #\<Gamma> Γ = (atom x' supp Γ' supp x supp b0 supp c0 supp Γ)"
proof - 
  have  "atom x' Γ' @ (x, b0, c0) #\<Gamma> Γ = (atom x' supp (Γ' @((x,b0,c0) #\<Gamma> Γ)))"
    using fresh_def by auto
  also have "... = (atom x' supp Γ' supp ((x,b0,c0) #\<Gamma> Γ))" using supp_append_by fast
  also have "... = (atom x' supp Γ' supp x supp b0 supp c0 supp Γ)" using supp_GCons supp_append_g supp_triple  by auto
  finally show ?thesis by fast
qed

lemma fresh_suffix[ms_fresh]:
  fixes Γ::Γ
  assumes "atom x Γ'@Γ"
  shows "atom x Γ"
  using assms by(induct  Γ' rule: Γ_induct, auto simp add: append_g.simps fresh_GCons)

lemma not_GCons_self [simp]:
  fixes xs::Γ
  shows "xs x #\<Gamma> xs"
  by (induct xs) auto

lemma not_GCons_self2 [simp]: 
  fixes xs::Γ
  shows "x #\<Gamma> xs xs"
  by (rule not_GCons_self [symmetric])

lemma fresh_restrict:
  fixes y::x and Γ::Γ
  assumes  "atom y (Γ' @ (x, b, c) #\<Gamma> Γ)"
  shows "atom y (Γ'@Γ)"
  using assms by(induct Γ' rule: Γ_induct, auto simp add:fresh_GCons fresh_GNil  )

lemma fresh_dom_free:
  assumes "atom x Γ" 
  shows "(x,b,c) toSet Γ"
  using assms proof(induct Γ rule: Γ_induct)
  case GNil
  then show ?case by auto
next
  case (GCons x' b' c' Γ')
  hence "xx'" using fresh_def fresh_GCons fresh_Pair supp_at_base by blast
  moreover have "atom x Γ'" using fresh_GCons GCons by auto
  ultimately show ?case using toSet.simps GCons by auto
qed

lemma Γ_set_intros: "x toSet ( x #\<Gamma> xs)" and "y toSet xs ==> y toSet (x #\<Gamma> xs)"
  by simp+

lemma fresh_dom_free2:
  assumes "atom x atom_dom Γ" 
  shows "(x,b,c) toSet Γ"
  using assms proof(induct Γ rule: Γ_induct)
  case GNil
  then show ?case by auto
next
  case (GCons x' b' c' Γ')
  hence "xx'" using fresh_def fresh_GCons fresh_Pair supp_at_base by auto
  moreover have "atom x atom_dom Γ'" using fresh_GCons GCons by auto
  ultimately show ?case using toSet.simps GCons by auto
qed

subsection Mutable Variable Context Lemmas

lemma supp_DNil: 
  shows "supp DNil = {}"
  by (simp add: supp_def)

lemma supp_DCons: 
  fixes xs::Δ
  shows "supp (x #\<Delta> xs) = supp x supp xs"
  by (simp add: supp_def Collect_imp_eq Collect_neg_eq)

lemma fresh_DNil[ms_fresh]:
  shows "a DNil"
  by (simp add: fresh_def supp_DNil)

lemma fresh_DCons[ms_fresh]: 
  fixes xs::Δ
  shows "a (x #\<Delta> xs) a x a xs"
  by (simp add: fresh_def supp_DCons)

instance Δ :: fs
  by (standard, induct_tac x, simp_all add: supp_DNil supp_DCons  finite_supp)

subsection Lookup Functions

nominal_function lookup :: ==> x ==> (b*c) option" where
  "lookup GNil x = None"
"lookup ((x,b,c)#\<Gamma>G) y = (if x=y then Some (b,c) else lookup G y)"
  by (auto,simp add: eqvt_def lookup_graph_aux_def, metis neq_GNil_conv surj_pair)
nominal_termination (eqvt) by lexicographic_order

nominal_function replace_in_g :: ==> x ==> c ==> Γ"  (_[__] [1000,0,0200where
  "replace_in_g GNil _ _ = GNil"
"replace_in_g ((x,b,c)#\<Gamma>G) x' c' = (if x=x' then ((x,b,c')#\<Gamma>G) else (x,b,c)#\<Gamma>(replace_in_g G x' c'))"
       apply(auto,simp add: eqvt_def replace_in_g_graph_aux_def)
  using surj_pair Γ.exhaust by metis
nominal_termination (eqvt) by lexicographic_order

text  Functions for looking up data-constructors in the Pi context

nominal_function lookup_fun :: ==> f ==> fun_def option" where
  "lookup_fun [] g = None"
|  "lookup_fun ((AF_fundef f ft)#Π) g = (if (f=g) then Some (AF_fundef f ft) else lookup_fun Π g)"
       apply(auto,simp add: eqvt_def lookup_fun_graph_aux_def )
  by (metis fun_def.exhaust neq_Nil_conv)
nominal_termination (eqvt)  by lexicographic_order

nominal_function lookup_td :: ==> string ==> type_def option" where
  "lookup_td [] g = None"
|  "lookup_td ((AF_typedef s lst ) # (Θ::Θ)) g = (if (s = g) then Some (AF_typedef s lst ) else lookup_td Θ g)"
|  "lookup_td ((AF_typedef_poly s bv lst ) # (Θ::Θ)) g = (if (s = g) then Some (AF_typedef_poly s bv lst ) else lookup_td Θ g)"
          apply(auto,simp add: eqvt_def lookup_td_graph_aux_def )
  by (metis type_def.exhaust neq_Nil_conv)
nominal_termination (eqvt)  by lexicographic_order

nominal_function name_of_type  ::"type_def ==> f "  where
  "name_of_type (AF_typedef f _ ) = f"
"name_of_type (AF_typedef_poly f _ _) = f"
       apply(auto,simp add: eqvt_def name_of_type_graph_aux_def )
  using type_def.exhaust by blast
nominal_termination (eqvt)  by lexicographic_order

nominal_function name_of_fun  ::"fun_def ==> f "  where
  "name_of_fun (AF_fundef f ft) = f"
     apply(auto,simp add: eqvt_def name_of_fun_graph_aux_def )
  using fun_def.exhaust by blast
nominal_termination (eqvt)  by lexicographic_order

nominal_function remove2 :: "'a::pt ==> 'a list ==> 'a list" where
  "remove2 x [] = []" |
  "remove2 x (y # xs) = (if x = y then xs else y # remove2 x xs)"
  by (simp add: eqvt_def remove2_graph_aux_def,auto+,meson list.exhaust)
nominal_termination (eqvt)  by lexicographic_order

nominal_function base_for_lit :: "l ==> b" where
  "base_for_lit (L_true) = B_bool "
"base_for_lit (L_false) = B_bool "
"base_for_lit (L_num n) = B_int "
"base_for_lit (L_unit) = B_unit " 
"base_for_lit (L_bitvec v) = B_bitvec"
                   apply (auto simp: eqvt_def base_for_lit_graph_aux_def )
  using l.strong_exhaust by blast
nominal_termination (eqvt) by lexicographic_order

lemma neq_DNil_conv: "(xs DNil) = (y ys. xs = y #\<Delta> ys)"
  by (induct xs) auto

nominal_function setD :: ==> (u*τ) set" where
  "setD DNil = {}"
"setD (DCons xbc G) = {xbc} (setD G)"
       apply (auto,simp add: eqvt_def setD_graph_aux_def )
  using neq_DNil_conv surj_pair by metis
nominal_termination (eqvt) by lexicographic_order

lemma eqvt_triple:
  fixes y::"'a::at" and ya::"'a::at" and xa::"'c::at" and va::"'d::fs" and s::s and sa::s and f::"s*'c*'d ==> s"
  assumes "atom y (xa, va)" and "atom ya (xa, va)" and 
    "c. atom c (s, sa) atom c (y, ya, s, sa) (y c) s = (ya c) sa"
    and "eqvt_at f (s,xa,va)" and "eqvt_at f (sa,xa,va)" and
    "atom c (s, va, xa, sa)" and "atom c (y, ya, f (s, xa, va), f (sa, xa, va))"
  shows "(y c) f (s, xa, va) = (ya c) f (sa, xa, va)"
proof -
  have " (y c) f (s, xa, va) = f ( (y c) (s,xa,va))" using assms eqvt_at_def by metis
  also have "... = f ( (y c) s, (y c) xa ,(y c) va)" by auto
  also have "... = f ( (ya c) sa, (ya c) xa ,(ya c) va)" proof - 
    have " (y c) s = (ya c) sa" using assms Abs1_eq_iff_all by auto
    moreover have  "((y c) xa) = ((ya c) xa)" using assms flip_fresh_fresh fresh_prodN by metis
    moreover have  "((y c) va) = ((ya c) va)" using assms flip_fresh_fresh fresh_prodN by metis
    ultimately show ?thesis by auto
  qed
  also have "... = f ( (ya c) (sa,xa,va))" by auto
  finally show ?thesis using assms eqvt_at_def by metis
qed

section Functions for bit list/vectors

inductive split :: "int ==> bit list ==> bit list * bit list ==> bool" where
  "split 0 xs ([], xs)"
"split m xs (ys,zs) ==> split (m+1) (x#xs) ((x # ys), zs)"
equivariance split
nominal_inductive split .

lemma split_concat:
  assumes "split n v (v1,v2)"
  shows "v = append v1 v2"
  using assms proof(induct "(v1,v2)" arbitrary: v1 v2 rule: split.inducts)
  case 1
  then show ?case by auto
next
  case (2 m xs ys zs x)
  then show ?case by auto
qed

lemma split_n:
  assumes "split n v (v1,v2)"
  shows "0 n n int (length v)"
  using assms proof(induct rule: split.inducts)
  case (1 xs)
  then show ?case by auto
next
  case (2 m xs ys zs x)
  then show ?case by auto
qed

lemma split_length:
  assumes "split n v (v1,v2)"
  shows "n = int (length v1)"
  using assms proof(induct  "(v1,v2)" arbitrary: v1 v2 rule: split.inducts)
  case (1 xs)
  then show ?case by auto
next
  case (2 m xs ys zs x)
  then show ?case by auto
qed

lemma obtain_split:
  assumes "0 n" and "n int (length bv)" 
  shows " bv1 bv2. split n bv (bv1 , bv2)" 
  using assms proof(induct bv arbitrary: n)
  case Nil
  then show ?case using split.intros by auto
next
  case (Cons b bv)
  show ?case proof(cases "n = 0")
    case True
    then show ?thesis using split.intros by auto
  next
    case False
    then obtain m where m:"n=m+1" using Cons 
      by (metis add.commute add_minus_cancel)
    moreover have "0 m" using False m Cons by linarith
    then obtain bv1 and bv2 where "split m bv (bv1 , bv2)" using Cons m by force
    hence "split n (b # bv) ((b#bv1), bv2)" using m split.intros by auto
    then show ?thesis by auto
  qed
qed

end

Messung V0.5 in Prozent
C=91 H=97 G=93

¤ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet am  2026-06-10) ¤

*© Formatika GbR, Deutschland






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.