Theory Indexed_Term

section ‹Indexed Terms›

text ‹We provide a method to index all subterms of a term by numbers.›

theory Indexed_Term
  imports 
    First_Order_Terms.Subterm_and_Context
begin

type_synonym index = int
type_synonym ('f, 'v) indexed_term = "(('f × ('f,'v)term × index), ('v × ('f,'v)term × index)) term"

fun index_term_aux :: "index  ('f, 'v) term  index × ('f, 'v) indexed_term"
  and index_term_aux_list :: "index  ('f, 'v) term list  index × ('f, 'v) indexed_term list"
  where
    "index_term_aux i (Var v) = (i + 1, Var (v,Var v, i))"
  | "index_term_aux i (Fun f ts) = (case index_term_aux_list i ts of (j, ss)  (j + 1, Fun (f,Fun f ts,j) ss))" 
  | "index_term_aux_list i [] = (i,[])" 
  | "index_term_aux_list i (t # ts) = (case index_term_aux i t of (j,s)  map_prod id (Cons s) (index_term_aux_list j ts))"


definition index_term :: "('f, 'v) term  ('f, 'v) indexed_term"
  where
    "index_term t = snd (index_term_aux 0 t)" 

fun unindex :: "('f, 'v) indexed_term  ('f, 'v) term"
  where
    "unindex (Var (v,_)) = Var v"
  | "unindex (Fun (f,_) ts) = Fun f (map unindex ts)"

fun stored :: "('f, 'v) indexed_term  ('f, 'v) term"
  where
    "stored (Var (v,(s,_))) = s"
  | "stored (Fun (f,(s,_)) ts) = s"

fun name_of :: "('a × 'b)  'a"
  where
    "name_of (a,_) = a"

fun index :: "('f, 'v) indexed_term  index"
  where
    "index (Var (_,(_,i))) = i"
  | "index (Fun (_,(_,i)) _) = i"

definition "index_term_prop f s = ( u. s  u  f (index u) = Some (unindex u)  stored u = unindex u)" 

lemma index_term_aux: fixes t :: "('f,'v)term" and ts :: "('f,'v)term list"
  shows "index_term_aux i t = (j,s)  unindex s = t  i < j  ( f. dom f = {i ..< j}  index_term_prop f s)" 
    and "index_term_aux_list i ts = (j,ss)  map unindex ss = ts  i  j 
    ( f. dom f = {i ..< j}  Ball (set ss) (index_term_prop f))" 
proof (induct i t and i ts arbitrary: j s and j ss rule: index_term_aux_index_term_aux_list.induct)
  case (1 i v)
  then show ?case by (auto intro!: exI[of _ "(λ _. None)(i := Some (Var v))"] split: if_splits simp: index_term_prop_def supteq_var_imp_eq) 
next
  case (2 i g ts j s)
  obtain k ss where rec: "index_term_aux_list i ts = (k,ss)" by force
  from 2(2)[unfolded index_term_aux.simps rec split]
  have j: "j = k + 1" and s: "s = Fun (g, Fun g ts, k) ss" by auto
  from 2(1)[OF rec] obtain f where fss: "map unindex ss = ts" and
    ik: "i  k" and f: "dom f = {i..<k}" " s. s  set ss  index_term_prop f s" 
    by auto
  have set: "{i..< k + 1} = insert k {i..<k}" using ik by auto
  define h where "h = f(k := Some (Fun g ts))" 
  show ?case unfolding s unindex.simps fss j set index_term_prop_def
  proof (intro conjI exI[of _ h] refl allI)
    show "i < k + 1" using ik by simp
    show "dom h = insert k {i..<k}" using ik f(1) unfolding h_def by auto
    fix u
    show "Fun (g, Fun g ts, k) ss  u  h (index u) = Some (unindex u)  stored u = unindex u" 
    proof (cases "u = Fun (g, Fun g ts, k) ss")
      case True
      thus ?thesis by (auto simp: fss h_def index_term_prop_def)
    next
      case False
      show ?thesis
      proof (intro impI)
        assume "Fun (g, Fun g ts, k) ss  u" 
        with False obtain si where "si  set ss" and "si  u"
          by (metis Fun_supt suptI)
        from f(2)[unfolded index_term_prop_def, rule_format, OF this] f(1) ik 
        show "h (index u) = Some (unindex u)  stored u = unindex u" unfolding h_def by auto
      qed
    qed
  qed
next
  case (4 i t ts j sss)
  obtain k s where rec1: "index_term_aux i t = (k,s)" by force
  with 4(3) obtain ss where rec2: "index_term_aux_list k ts = (j,ss)" and sss: "sss = s # ss" 
    by (cases "index_term_aux_list k ts", auto)
  from 4(1)[OF rec1] obtain f where fs: "unindex s = t" and ik: "i < k" and f: "dom f = {i..<k}" 
    "index_term_prop f s" by auto
  from 4(2)[unfolded rec1, OF refl rec2] obtain g where fss: "map unindex ss = ts" and kj: "k  j" 
    and g: "dom g = {k..<j}" " si. si  set ss  index_term_prop g si"  
    by auto
  define h where "h = (λ n. if n  {i..<k} then f n else g n)" 
  show ?case unfolding sss list.simps fs fss
  proof (intro conjI exI[of _ h] refl allI ballI)
    have "dom h = {i ..< k}  {k ..< j}" unfolding h_def using f(1) g(1) by force
    also have " = {i ..< j}" using ik kj by auto
    finally show "dom h = {i..<j}" by auto
    show "i  j" using ik kj by auto
    fix si
    assume si: "si  insert s (set ss)"
    show "index_term_prop h si"
    proof (cases "si = s")
      case True
      from f show ?thesis unfolding True h_def index_term_prop_def by auto
    next
      case False
      with si have si: "si  set ss" by auto
      have disj: "{i..<k}  {k..<j} = {}" by auto
      from g(1) g(2)[OF si]
      show ?thesis unfolding index_term_prop_def h_def using disj
        by (metis disjoint_iff domI)
    qed
  qed
qed auto


lemma index_term_index_unindex: " f.  t. index_term s  t  f (index t) = unindex t  stored t = unindex t" 
proof -
  obtain t i where aux: "index_term_aux 0 s = (i,t)" by force
  from index_term_aux(1)[OF this] show ?thesis unfolding index_term_def aux index_term_prop_def by force
qed

lemma unindex_index_term[simp]: "unindex (index_term s) = s"
proof -
  obtain t i where aux: "index_term_aux 0 s = (i,t)" by force
  from index_term_aux(1)[OF this] show ?thesis unfolding index_term_def aux by force
qed

end