Theory Inversion

Up to index of Isabelle/HOL/Tables

theory Inversion = Tables2:
header {* Inversion of Normal Tables *}

theory Inversion = Tables2:

subsection {* One-Dimensional Inversion *}

consts
  inverse1 :: "('a,('b,'c) T) T \<Rightarrow> ('b,('a,'c) T) T"

defs
  inverse1_def: "inverse1 == tFold addH2 hConc"

lemma inverse1_addH[simp]:
  "inverse1 (addH h t) = addH2 h t"
by (unfold inverse1_def, simp)

lemma inverse1_hConc[simp]:
  "inverse1 (hConc t1 t2) = hConc (inverse1 t1) (inverse1 t2)"
by (unfold inverse1_def, simp)

lemma tFold_tFold_inverse1:
 "\<lbrakk> assoc c2; assoc c4;
    \<And> h2 h1 t . a2 h2 (a1 h1 t) = a3 h1 (a4 h2 t);
    \<And> h t u   . a3 h  (c4 t  u) = c2 (a3 h t) (a3 h u)
  \<rbrakk> \<Longrightarrow>
  tFold a2 c2 (tMap (tFold a1 c1) (inverse1 t)) =
  tFold a3 c2 (tMap (tFold a4 c4) t)"
apply (induct_tac t rule: T_induct)
apply (induct_tac t0 rule: T_induct, simp)
apply (induct_tac t1 rule: T_induct, simp)
apply simp
apply (subgoal_tac "tFold (\<lambda>ha t0. a3 h (a4 ha t0)) c2 t1a = a3 h (tFold a4 c4 t1a)", simp)
apply (induct_tac t1a rule: T_induct, simp, simp)
txt {* original induction, second case: *}
apply (simp del: tFold_tMap)
done

lemma tFold_tFold0_inverse1:
 "\<lbrakk> assoc c2; assoc c4;
    \<And> h t u   . a2 (c4 t u) h = c2 (a2 t h) (a2 u h)
  \<rbrakk> \<Longrightarrow>
  tFold a2 c2 (tMap (tFold0 c1) (inverse1 t)) =
  tFold (flip a2) c2 (tMap (tFold0 c4) t)"
by (unfold tFold0_def, rule tFold_tFold_inverse1, simp_all)


subsection {* spread1 *}

consts spread1 :: "'a neList \<Rightarrow> 'b \<Rightarrow> ('a, 'b) T"

defs spread1_def: "spread1 hs t == foldr1 hConc (map1 (\<lambda>h. addH h t) hs)"

lemma regSkelOuter2_spread1[simp]:
 "regSkelOuter2 (spread1 hs t) = Some (hs, headers t)"
apply (subst neList_append_induct [of "% hs . regSkelOuter2 (spread1 hs t) = Some (hs, headers t)"], simp_all)
txt {* WHy does standard induction not work here?! *}
apply (unfold spread1_def, simp_all)
done

lemma spread1_singleton[simp]: "spread1 (singleton h) t = addH h t"
by (simp add: spread1_def)

lemma spread1_append[simp]:
 "spread1 (append hs1 hs2) t = hConc (spread1 hs1 t) (spread1 hs2 t)"
by (simp add: spread1_def)

lemma spread1_tFold_append:
 "spread1 (tFold f append t1) t = tFold (% h0 t0 . spread1 (f h0 t0) t) hConc t1"
by (induct_tac t1 rule: T_induct, simp_all)

lemma spread1_hConc_0:
 "ALL t1 . spread1 hs (hConc t1 t2) = vConc (spread1 hs t1) (spread1 hs t2)"
apply (induct_tac hs rule: neList_append_induct, simp)
apply simp
apply (rule allI)
apply (subst vConc_hConc)
  apply simp
  apply (rule conjI, simp, simp)
  apply simp
  apply simp
  apply simp
apply simp
done

lemma spread1_hConc:
 "spread1 hs (hConc t1 t2) = vConc (spread1 hs t1) (spread1 hs t2)"
by (insert spread1_hConc_0 [of hs t2], auto)

lemma tMap_f_spread1:
  "tMap f (spread1 hs t) = spread1 hs (f t)"
by (induct_tac hs rule: neList_append_induct, simp_all)

lemma tFold_spread1:
 "assoc c \<Longrightarrow> tFold a c (spread1 hs t) = foldr1 c (map1 (% h . a h t) hs)"
by (induct_tac hs rule: neList_append_induct, simp_all)


subsection {* spread2 *}

text {* This was used in the previous definition of @{text "dconc"}. *}
consts
 spread2 :: "'a neList \<Rightarrow> ('b,'c) T \<Rightarrow> ('b,('a,'c) T) T"

defs
 spread2_def: "spread2 hs t == foldr1 vConc (map1 (% h . addH2 h t) hs)"

lemma spread2_singleton[simp]:
  "spread2 (singleton h) t = addH2 h t"
by (unfold spread2_def, simp)

lemma spread2_append[simp]:
  "spread2 (append hs1 hs2) t = vConc (spread2 hs1 t) (spread2 hs2 t)"
by (unfold spread2_def, simp)

lemma spread2_cons1[simp]:
  "spread2 (cons1 h hs) t = vCons (h,t) (spread2 hs t)"
by (simp add: cons1 vCons)

lemma headers_spread2[simp]:
 "headers (spread2 hs t) = headers t"
by (induct_tac hs rule: neList_cons_induct, simp_all)

lemma regSkelOuter2_spread2_0:
  "ALL hs2 . regSkelOuter2 (spread2 hs2 t) = Some (headers t,hs2)"
apply (induct_tac t rule: T_cons_induct, simp)
apply (rule allI, induct_tac hs2 rule: neList_append_induct)
apply simp
apply simp
apply (rule allI)
apply (erule mp1)
apply (rule_tac x=t2 in spec)
apply (induct_tac hs2 rule: neList_cons_induct)
apply (intro strip, simp)
txt {* @{text "hs2 = cons1 x xs"} *}
apply (intro strip, simp)
apply (drule_tac x=xa in spec)
apply simp
apply (subst regSkelOuter2_vCons, simp)
apply (simp add: cons1)
done

lemma regSkelOuter2_spread2[simp]:
  "regSkelOuter2 (spread2 hs2 t) = Some (headers t,hs2)"
by (rule regSkelOuter2_spread2_0 [THEN spec])

lemma spread2_hConc_0:
  "ALL t1 t2 . spread2 hs2 (hConc t1 t2) = hConc (spread2 hs2 t1) (spread2 hs2 t2)"
apply (induct_tac hs2 rule: neList_append_induct)
apply simp
apply simp
apply (intro strip)
apply (subst vConc_hConc)
  apply simp
  apply (rule conjI)
  apply simp
  apply simp
  apply simp
  apply simp
  apply simp
apply simp
done

lemma spread2_hConc[simp]:
  "spread2 hs2 (hConc t1 t2) = hConc (spread2 hs2 t1) (spread2 hs2 t2)"
by (insert spread2_hConc_0, auto)

lemma spread2_addH:
  "spread2 hs (addH h t) = addH h (foldr1 hConc (map1 (% h2 . addH h2 t) hs))"
by (induct_tac hs rule: neList_append_induct, simp_all)

lemma spread2_tFold_hConc:
  "spread2 hs2 (tFold a hConc t) = tFold (% h t . spread2 hs2 (a h t)) hConc t"
by (induct_tac t rule: T_induct, simp_all)

lemma tMap_tFold_spread2:
 "assoc c \<Longrightarrow>
  tMap (tFold a c) (spread2 hs t) =
  tMap (% t0 . foldr1 c (map1 (\<lambda>h2. a h2 t0) hs)) t"
by (induct_tac t rule: T_induct, simp_all add: spread2_addH map1_contract_comp tFold_foldr1_hConc o_def)

subsection {* delH1 *}

consts delH1 :: "('a,'b) T \<Rightarrow> 'b"
defs delH1_def: "delH1 == tFold (% h t . t) const"

lemma delH1_hConc[simp]:
   "delH1 (hConc t1 t2) = delH1 t1"
by (simp add: delH1_def)

lemma delH1_addH[simp]:
   "delH1 (addH h t) = t"
by (simp add: delH1_def)

lemma delH1_hCons[simp]:
   "delH1 (hCons (h,t0) t) = t0"
by (simp add: hCons)

lemma delH1_tFold_hConc[simp]:
 "delH1 (tFold f hConc t) = delH1 (uncurry f (hHead t))"
by (induct_tac t rule: T_induct, simp_all)

lemma headers_delH1__reg2_0:
  "ALL hs1 hs2 . regSkelOuter2 t1 = Some (hs1, hs2) \<longrightarrow> headers (delH1 t1) = hs2"
apply (induct_tac t1 rule: T_induct, simp_all)
apply (intro strip)
apply (drule optThen_result_Some, erule exE, erule conjE)
apply (drule optThen_result_Some, erule exE, erule conjE)
apply (split split_if_asm, simp_all)
apply (case_tac y, case_tac ya, simp)
done

lemma headers_delH1__reg2[simp]:
  "regSkelOuter2 t1 = Some (hs1, hs2) \<Longrightarrow> headers (delH1 t1) = hs2"
by (insert headers_delH1__reg2_0, auto)

lemma delH1_addH2[simp]: "delH1 (addH2 h t) = addH h (delH1 t)"
by (induct_tac t rule: T_induct, simp_all)

lemma delH1_vConc_0:
 "ALL hs1a hs1b hs2a hs2b .
  regSkelOuter2 t1 = Some (hs1a, hs1b) \<longrightarrow>
  regSkelOuter2 t2 = Some (hs2a, hs2b) \<longrightarrow>
  delH1 (vConc t1 t2) = hConc (delH1 t1) (delH1 t2)"
apply (induct_tac t1 rule: T_cons_induct, simp_all)
apply (induct_tac t2 rule: T_cons_induct, simp_all)
apply (intro strip, erule exE, erule exE)
apply (drule optThen_result_Some, erule exE, erule conjE)
apply (split split_if_asm, simp_all)
apply (case_tac p, case_tac y, simp)
apply (induct_tac t2 rule: T_cons_induct, simp_all)
apply (intro strip, erule exE, erule exE)
apply (drule optThen_result_Some, erule exE, erule conjE)
apply (split split_if_asm, simp_all)
apply (case_tac p, case_tac y, simp)
apply (intro strip, erule exE, erule exE, erule exE, erule exE)
apply simp
apply (case_tac p, case_tac pa, simp)
done

lemma delH1_vConc:
 "\<lbrakk> regSkelOuter2 t1 = Some (hs1a, hs1b);
    regSkelOuter2 t2 = Some (hs2a, hs2b)
  \<rbrakk> \<Longrightarrow>
  delH1 (vConc t1 t2) = hConc (delH1 t1) (delH1 t2)"
by (insert delH1_vConc_0, auto)

lemma delH1_tMap_const[simp]: "delH1 (tMap (const t2) t1) = t2"
by (induct_tac t1 rule: T_induct, simp_all)

lemma delH1_tMap_CONST[simp]: "delH1 (tMap (% x . t2) t1) = t2"
by (induct_tac t1 rule: T_induct, simp_all)

subsection {* delH2 *}

consts delH2 :: "('a,('b,'c) T) T \<Rightarrow> ('a,'c) T"

defs delH2_def: "delH2 == tMap delH1"

lemma delH2_hConc[simp]:
   "delH2 (hConc t1 t2) = hConc (delH2 t1) (delH2 t2)"
by (simp add: delH2_def)

lemma delH2_addH[simp]:
   "delH2 (addH h t) = addH h (delH1 t)"
by (simp add: delH2_def)

lemma delH2_hCons[simp]:
   "delH2 (hCons (h,t0) t) = hCons (h, delH1 t0) (delH2 t)"
by (simp add: hCons)

lemma delH2_addH2[simp]:
   "delH2 (addH2 h t) = t"
by (induct_tac t rule: T_induct, simp_all)

lemma headers_delH2[simp]: "headers (delH2 t) = headers t"
by (induct_tac t rule: T_induct, simp_all)

lemma delH2_vConc_0:
 "ALL hs1 hs2a t2 hs2b .
  regSkelOuter2 t1 = Some (hs1, hs2a) \<longrightarrow>
  regSkelOuter2 t2 = Some (hs1, hs2b) \<longrightarrow>
  delH2 (vConc t1 t2) = delH2 t1"
apply (induct_tac t1 rule: T_cons_induct, simp_all)
apply (rule allI)
apply (rule impI)
apply (rule allI)
apply (erule exE)+
apply (drule optThen_result_Some, erule exE, erule conjE, simp)
apply (split split_if_asm, simp_all)
apply (erule conjE, case_tac y, simp)
apply (induct_tac t2a rule: T_cons_induct, simp_all)
apply (rule impI, rotate_tac -1, drule sym, simp)
apply (intro strip)
apply (erule exE)+
apply (drule optThen_result_Some, erule exE, erule conjE, simp)
apply (split split_if_asm, simp_all)
apply (erule conjE, case_tac p, case_tac pa, case_tac ya, simp)
apply (drule_tac x=t2b in spec, simp)
apply (rotate_tac 2, drule sym, simp, drule cons1_inj, simp)
done

lemma delH2_vConc[simp]:
 "\<lbrakk> regSkelOuter2 t1 = Some (hs1, hs2a);
    regSkelOuter2 t2 = Some (hs1, hs2b) \<rbrakk> \<Longrightarrow>
  delH2 (vConc t1 t2) = delH2 t1"
by (insert delH2_vConc_0 [of t1], auto)

lemma delH2_spread2[simp]:
 "delH2 (spread2 hs t) = t"
apply (induct_tac t rule: T_induct, simp_all)
apply (induct_tac hs rule: neList_append_induct, simp_all)
apply (subst delH2_vConc, simp_all)
apply (rule conjI, simp_all)
apply (rule conjI, simp_all)
done

lemma delH2_tMap_const:
  "delH2 (tMap (const t2) t1) = tMap (const (delH1 t2)) t1"
by (induct_tac t1 rule: T_induct, simp_all)

lemma delH2_tMap_CONST:
  "delH2 (tMap (% x . t2) t1) = tMap (const (delH1 t2)) t1"
by (induct_tac t1 rule: T_induct, simp_all)

subsection {* Third Dimension Operators *}

consts addH3 :: "'c \<Rightarrow> ('a, ('b,'d) T) T \<Rightarrow> ('a, ('b, ('c, 'd) T) T) T"

defs addH3_def: "addH3 == tMap \<circ> addH2"

lemma delH1_addH3[simp]: "delH1 (addH3 h t) = addH2 h (delH1 t)"
by (unfold addH3_def, induct_tac t rule: T_induct, simp_all)

consts delH3 :: "('a, ('b, ('c , 'd) T) T) T \<Rightarrow> ('a, ('b,'d) T) T"

defs delH3_def: "delH3 == tMap delH2"

subsection {* Slimming Operators *}

text {* These operators slim down a selected dimension
in the regular table skeleton
to a singleton containing a supplied entry @{text "u"}. *}

consts slimH1 :: "'a \<Rightarrow> ('c,'b) T \<Rightarrow> ('a,'b) T"

defs slimH1_def[simp]: "slimH1 h1 t == addH h1 (delH1 t)"

lemma tFold_slimH1:
  "assoc c \<Longrightarrow> tFold a c (slimH1 u t) = tFold (% h0 t0 . a u t0) const t"
apply (induct_tac t rule: T_induct, simp_all del: const)
apply (subst const)
apply (simp (no_asm_simp) del: const)
done

lemma headers_slimH1[simp]: "headers (slimH1 u t) = singleton u"
by simp

consts slimH2 :: "'b \<Rightarrow> ('a,('d,'c) T) T \<Rightarrow> ('a,('b,'c) T) T"

defs slimH2_def[simp]: "slimH2 h2 t == addH2 h2 (delH2 t)"

lemma slimH2_tMap: "slimH2 h2 = tMap (slimH1 h2)"
by (rule ext, induct_tac x rule: T_induct, simp_all)

lemma slimH2_slimH2[simp]: "slimH2 u (slimH2 v t) = slimH2 u t"
by simp

lemma slimH2_addH[simp]: "slimH2 u (addH h t) = addH h (slimH1 u t)"
by simp

lemma slimH2_hConc[simp]:
  "slimH2 u (hConc t1 t2) = hConc (slimH2 u t1) (slimH2 u t2)"
by simp

lemma slimH2_as_tFold[simp]:
  "tFold (\<lambda>h t. addH h (slimH1 u t)) hConc t = slimH2 u t"
by (induct_tac t rule: T_induct, simp_all)

lemma slimH2_addH2[simp]: "slimH2 u (addH2 h2 t) = addH2 u t"
by simp

lemma headers_slimH2[simp]: "headers (slimH2 u t) = headers t"
by (induct_tac t rule: T_induct, simp_all)

lemma regSkelOuter2_slimH2[simp]:
 "regSkelOuter2 (slimH2 u t) = Some (headers t, singleton u)"
by (induct_tac t rule: T_induct, simp_all)

lemma slimH2_tFold_hConc[simp]:
  "slimH2 u (tFold f hConc t) = tFold (% h t . slimH2 u (f h t)) hConc t"
by (induct_tac t rule: T_induct, simp_all del: slimH2_def)

lemma slimH2_tFold_addH2_hConc[simp]:
  "slimH2 u (tFold (% h . addH2 v) hConc t) = tFold (% h . addH2 u) hConc t"
by (induct_tac t rule: T_induct, simp_all del: slimH2_def)

lemma del1_slimH2_isConst[simp]:
  "delH1 (slimH2 u (t1 :: ('a, ('b, unit) T) T)) = delH1 (slimH2 u t2)"
by simp

lemma tFold_slimH2:
  "assoc c \<Longrightarrow> tFold a c (slimH2 u t) = tFold (% h0 t0 . a h0 (slimH1 u t0)) c t"
by (induct_tac t rule: T_induct, simp_all)

consts slimH3 :: "'c \<Rightarrow> ('a, ('b, ('e , 'd) T) T) T \<Rightarrow> ('a, ('b, ('c, 'd) T) T) T"

defs slimH3_def: "slimH3 == tMap \<circ> slimH2"

lemma slimH3_expand: "slimH3 u t = addH3 u (delH3 t)"
by (induct_tac t rule: T_induct, simp_all add: delH3_def addH3_def slimH3_def)

lemma slimH3_addH[simp]: "slimH3 u (addH h t) = addH h (slimH2 u t)"
by (simp add: slimH3_def del: slimH2_def)

lemma slimH3_hConc[simp]: "slimH3 u (hConc t1 t2) = hConc (slimH3 u t1) (slimH3 u t2)"
by (simp add: slimH3_def del: slimH2_def)

lemma spread1_slimH2: "spread1 hs (slimH2 u t) = slimH3 u (spread1 hs t)"
by (induct_tac hs rule: neList_append_induct, simp_all del: slimH2_def slimH3_def)

lemma tFold_slimH3:
  "assoc c \<Longrightarrow> tFold a c (slimH3 u t) = tFold (% h0 t0 . a h0 (slimH2 u t0)) c t"
by (induct_tac t rule: T_induct, simp_all del: slimH2_def slimH3_def)

lemma tMap_f_slimH3:
  "tMap f (slimH3 u t) = tMap (% t0 . f (slimH2 u t0)) t"
apply (unfold slimH3_def)
apply (unfold comp_def)
apply (subst tMap_tMap)
apply (unfold comp_def)
apply (rule refl)
done

subsection {* Right-Updating Horizontal Concatenation *}

consts hConcU :: "('c \<Rightarrow> ('a,'b) T) \<Rightarrow> ('a,'b) T \<Rightarrow> 'c \<Rightarrow> ('a,'b) T"

defs hConcU_def[simp]: "hConcU u t1 t2 == hConc t1 (u t2)"

lemma hConcU_assoc[simp]:
 "\<lbrakk> \<And> t . u (u t) = u t;
    \<And> t1 t2 . u (hConc t1 t2) = hConc (u t1) (u t2)
  \<rbrakk> \<Longrightarrow> assoc (hConcU u)"
by (rule assoc_intro, simp)

lemma U_hConcU[simp]:
 "\<lbrakk> \<And> t . u (u t) = u t;
    \<And> t1 t2 . u (hConc t1 t2) = hConc (u t1) (u t2)
  \<rbrakk> \<Longrightarrow> u (hConcU u t1 t2) = hConc (u t1) (u t2)"
by simp

lemma U_tFold_hConcU[simp]:
 "\<lbrakk> \<And> t . u (u t) = u t;
    \<And> t1 t2 . u (hConc t1 t2) = hConc (u t1) (u t2)
  \<rbrakk> \<Longrightarrow> u (tFold f (hConcU u) t) = tFold (% h0 t0 . u (f h0 t0)) hConc t"
by (induct_tac t rule: T_induct, simp_all del: hConcU_def)

consts hConcSH2 :: "'b \<Rightarrow> ('a,('b,'c) T) T \<Rightarrow> ('a,('d,'c) T) T \<Rightarrow> ('a,('b,'c) T) T"

defs hConcSH2_def: "hConcSH2 u == hConcU (slimH2 u)"

lemma hConcSH2_assoc[simp]: "assoc (hConcSH2 u)"
by (rule assoc_intro, simp add: hConcSH2_def)

lemma slimH2_hConcSH2[simp]:
  "slimH2 u (hConcSH2 u t1 t2) = hConc (slimH2 u t1) (slimH2 u t2)"
by (unfold hConcSH2_def, simp del: slimH2_def)

lemma slimH2_tFold_hConcSH2[simp]:
  "slimH2 u (tFold f (hConcSH2 u) t) = tFold (% h t . slimH2 u (f h t)) hConc t"
by (induct_tac t rule: T_induct, simp_all del: slimH2_def)


subsection {* Diagonal Table Concatenation *}

text {* Diagonal concatenation allocates the two last arguments
as blocks on the main diagonal and fills the remainder with
``empty'' tables created using the first argument.

Since we shall use this as combinator of a table fold,
we need its associativity, but that holds only on tables
that are regular in their outer two dimensions.
For this reason we define diagonal concatenation
on the subtype @{text "regT2"}.
*}

consts dConc :: "(('b,'c) T \<Rightarrow> ('b,'c) T) \<Rightarrow>
                  ('a,'b,'c) regT2 \<Rightarrow>
                  ('a,'b,'c) regT2 \<Rightarrow>
                  ('a,'b,'c) regT2"


defs dConc_def: "dConc h t1 t2 ==
     let t1' = Rep_regT2 t1;
         t2' = Rep_regT2 t2
     in Abs_regT2
        (hConc (vConc t1'               (tMap (const (h (delH1 t2'))) t1'))
               (vConc (tMap (const (h (delH1 t1'))) t2') t2'              )
        )"

lemma dConc[simp]:
  "\<lbrakk> regSkelOuter2 t1 = Some (cs1, hs1);
     regSkelOuter2 t2 = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
   dConc h (Abs_regT2 t1) (Abs_regT2 t2)
    = Abs_regT2
        (hConc (vConc t1                         (tMap (const (h (delH1 t2))) t1))
               (vConc (tMap (const (h (delH1 t1))) t2)  t2)
        )"
apply (unfold dConc_def, simp only: Let_def regT2_def)
apply (subst Abs_regT2_inverse, simp add: regT2_def, fast)+
apply simp
done

lemma dConc1:
  "\<lbrakk> regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
   dConc h t1 t2
    = Abs_regT2
        (hConc (vConc (Rep_regT2 t1) (tMap (const (h (delH1 (Rep_regT2 t2)))) (Rep_regT2 t1)))
               (vConc (tMap (const (h (delH1 (Rep_regT2 t1)))) (Rep_regT2 t2)) (Rep_regT2 t2))
        )"
apply (frule_tac h=h and "t2.0"="Rep_regT2 t2" in dConc, assumption)
apply (simp only: Rep_regT2_inverse)
done

lemma regSkelOuter2_dConcDef[simp]:
  "\<lbrakk> \<And> t . headers (h t) = headers t;
    regSkelOuter2 t1 = Some (cs1, hs1);
     regSkelOuter2 t2 = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
  regSkelOuter2
        (hConc (vConc t1 (tMap (const (h (delH1 t2))) t1))
               (vConc (tMap (const (h (delH1 t1))) t2)  t2))
    = Some (append cs1 cs2, append hs1 hs2)"
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (rotate_tac -2, frule regSkelOuter2_eq_Some)
apply (cut_tac "t1.0"="t1"  and "t2.0"="tMap (const (h (delH1 t2))) t1" in regSkelOuter2_vConc)
    apply assumption
    apply (simp (no_asm_simp))
    apply (rule conjI)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (cut_tac "t1.0"="tMap (const (h (delH1 t1))) t2"  and "t2.0"="t2" in regSkelOuter2_vConc)
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp))
apply (rotate_tac -1, frule regSkelOuter2_eq_Some) 
apply (simp (no_asm_simp))
apply (subst headers_delH1__reg2, assumption)
apply (subst headers_delH1__reg2, assumption)
apply (simp (no_asm_simp))
done

lemma regSkelOuter2_dConc[simp]:
  "\<lbrakk> \<And> t . headers (h t) = headers t;
    regSkelOuter2 t1 = Some (cs1, hs1);
     regSkelOuter2 t2 = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
   regSkelOuter2 (Rep_regT2 (dConc h (Abs_regT2 t1) (Abs_regT2 t2)))
    = Some (append cs1 cs2, append hs1 hs2)"
apply (subst dConc)
    apply assumption
    apply assumption
apply (subst Abs_regT2_inverse, rule regT2)
apply (subst regSkelOuter2_dConcDef)
  apply simp
  apply assumption
  apply assumption
  apply simp
  apply (rule conjI, simp, simp)
apply (subst regSkelOuter2_dConcDef)
  apply simp
  apply assumption
  apply assumption
  apply simp
done

lemma dConc2[simp]:
  "\<lbrakk> \<And> t . headers (h t) = headers t;
     regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
   Rep_regT2 (dConc h t1 t2)
    = hConc (vConc (Rep_regT2 t1) (tMap (const (h (delH1 (Rep_regT2 t2)))) (Rep_regT2 t1)))
            (vConc (tMap (const (h (delH1 (Rep_regT2 t1)))) (Rep_regT2 t2)) (Rep_regT2 t2))"
apply (subst dConc1)
  apply assumption+
apply (subst Abs_regT2_inverse, rule regT2)
apply (subst regSkelOuter2_dConcDef)
  apply simp
  apply assumption
  apply assumption
  apply simp
  apply (rule conjI, simp, simp)
apply (simp del: const)
done

lemma regSkelOuter2_dConc1[simp]:
  "\<lbrakk> \<And> t . headers (h t) = headers t;
    regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
   regSkelOuter2 (Rep_regT2 (dConc h t1 t2))
    = Some (append cs1 cs2, append hs1 hs2)"
apply (subst dConc2)
    apply simp
    apply assumption
    apply assumption
apply (subst regSkelOuter2_dConcDef)
  apply simp
  apply assumption
  apply assumption
apply simp
done

lemma headers_dConc[simp]:
  "\<lbrakk> \<And> t . headers (h t) = headers t
   \<rbrakk> \<Longrightarrow>
   headers (Rep_regT2 (dConc h t1 t2)) = append (headers (Rep_regT2 t1)) (headers (Rep_regT2 t2))"
apply (cut_tac x=t1 in Rep_regT2)
apply (cut_tac x=t2 in Rep_regT2)
apply (simp add: regT2_def)
apply (drule regularOuter2, erule exE, erule exE)
apply (drule regularOuter2, erule exE, erule exE)
apply (subst dConc2)
    apply simp
    apply assumption
    apply assumption
apply simp
apply (subst headers_vConc)
  apply simp
  apply (rule conjI)
  apply simp
  apply simp
  apply simp
  apply (rule conjI)
  apply (rule sym, simp)
  apply simp
apply (subst headers_vConc)
  apply simp
  apply (rule conjI)
  apply simp
  apply simp
  apply (simp del: const)
apply (simp del: const)
done

lemma reg2dim2_dConc[simp]:
  "\<lbrakk> \<And> t . headers (h t) = headers t;
     regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
   reg2dim2 (dConc h t1 t2) = append hs1 hs2"
apply (cut_tac h=h and "t1.0"="Rep_regT2 t1" and "t2.0"="Rep_regT2 t2" in regSkelOuter2_dConc)
  apply (simp (no_asm_simp))
  apply assumption+
apply (simp only: Rep_regT2_inverse)
apply (subst Rep_regT2_inverse [THEN sym])
apply (rule reg2dim2)
apply assumption
done

lemma cs_dConc[simp]:
  "\<lbrakk> \<And> t . headers (h t) = headers t;
     \<And> t . h (h t) = h t;
     \<And> t1 t2 . h (hConc t1 t2) = hConc (h t1) (h t2);
     regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2)
   \<rbrakk> \<Longrightarrow>
   h (delH1 (Rep_regT2 (dConc h t1 t2))) =
   hConc (h (delH1 (Rep_regT2 t1)))
         (h (delH1 (Rep_regT2 t2)))"
apply (cut_tac h=h and "t1.0"="Rep_regT2 t1" and "t2.0"="Rep_regT2 t2" in regSkelOuter2_dConc)
  apply (simp (no_asm_simp))
  apply assumption+
apply (subst dConc1)
  apply assumption+
apply (subst Abs_regT2_inverse, rule regT2)
  apply (subst regSkelOuter2_dConcDef)
    apply simp
    apply assumption
    apply assumption
    apply (simp (no_asm_simp))
    apply (rule conjI)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
apply (simp (no_asm_simp))
apply (subst delH1_vConc)
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (rule sym, simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (simp del: const)
done

lemma dConc_assoc[simp]:
 "\<lbrakk> \<And> t . headers (h t) = headers t;
    \<And> t . h (h t) = h t;
    \<And> t1 t2 . h (hConc t1 t2) = hConc (h t1) (h t2)
  \<rbrakk> \<Longrightarrow> assoc (dConc h)"
apply (rule assoc_intro)
apply (cut_tac x=x in Rep_regT2)
apply (cut_tac x=y in Rep_regT2)
apply (cut_tac x=z in Rep_regT2)
apply (simp add: regT2_def)
apply (drule regularOuter2, erule exE, erule exE)
apply (drule regularOuter2, erule exE, erule exE)
apply (drule regularOuter2, erule exE, erule exE)
apply (cut_tac h=h and "t1.0"="Rep_regT2 x" and "t2.0"="Rep_regT2 y" in regSkelOuter2_dConc)
  apply (simp (no_asm_simp))
  apply assumption+
apply (cut_tac h=h and "t1.0"="Rep_regT2 y" and "t2.0"="Rep_regT2 z" in regSkelOuter2_dConc)
  apply (simp (no_asm_simp))
  apply assumption+
apply (simp only: Rep_regT2_inverse)
apply (cut_tac h=h and "t1.0"="Rep_regT2 (dConc h x y)" and "t2.0"="Rep_regT2 z" in regSkelOuter2_dConc)
  apply (simp (no_asm_simp))
  apply assumption+
apply (cut_tac h=h and "t1.0"="Rep_regT2 x" and "t2.0"="Rep_regT2 (dConc h y z)" in regSkelOuter2_dConc)
  apply (simp (no_asm_simp))
  apply assumption+
apply (simp only: Rep_regT2_inverse)
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (cut_tac h=h and "t1.0"="dConc h x y" and "t2.0"="z" in dConc1)
  apply assumption
  apply assumption
apply (cut_tac h=h and "t1.0"="x" and "t2.0"="dConc h y z" in dConc1)
  apply assumption
  apply assumption
apply (simp (no_asm_simp))
apply (subst cs_dConc [of h])
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (subst cs_dConc [of h])
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (subst dConc2 [of h])
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (subst dConc2 [of h])
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
txt {* Lots of preparations *}
apply (frule_tac t="Rep_regT2 x" in reg2dim2)
apply (frule_tac t="Rep_regT2 y" in reg2dim2)
apply (frule_tac t="Rep_regT2 z" in reg2dim2)
apply (simp only: Rep_regT2_inverse)
apply (cut_tac "t1.0"="Rep_regT2 y" and "t2.0"="(tMap (const (h (delH1 (Rep_regT2 z)))) (Rep_regT2 y))" in regSkelOuter2_vConc)
    apply assumption
    apply (simp (no_asm_simp))
    apply (rule conjI)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (rule sym, simp (no_asm_simp))
apply (rotate_tac -1, frule regSkelOuter2_eq_Some) 
apply (cut_tac "t1.0"="(tMap (const (h (delH1 (Rep_regT2 y)))) (Rep_regT2 z))" and "t2.0"="Rep_regT2 z" in regSkelOuter2_vConc)
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp))
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (cut_tac "t1.0"="Rep_regT2 x" and "t2.0"="(tMap (const (h (delH1 (Rep_regT2 y)))) (Rep_regT2 x))" in regSkelOuter2_vConc)
    apply assumption
    apply (simp (no_asm_simp))
    apply (rule conjI)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (rule sym, simp (no_asm_simp))
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
apply (cut_tac "t1.0"="(tMap (const (h (delH1 (Rep_regT2 x)))) (Rep_regT2 y))" and "t2.0"="Rep_regT2 y" in regSkelOuter2_vConc)
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp))
apply (rotate_tac -1, frule regSkelOuter2_eq_Some)
txt {* end of preparations *}
txt {* The remainder is rewriting to normal form with @{text "vConc_hConc"}. *}
apply (simp (no_asm_simp) del: const)
apply (subst vConc_hConc)
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp))
    apply (subst headers_delH1__reg2, assumption)
    apply (subst headers_delH1__reg2, assumption)
  apply (simp (no_asm_simp))
apply (subst vConc_hConc)
  apply assumption
  apply (simp (no_asm_simp) del: const)
  apply (rule conjI)
  apply (simp (no_asm_simp))
    apply (subst headers_delH1__reg2, assumption)
    apply (subst headers_delH1__reg2, assumption)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp) del: const)
  apply (simp (no_asm_simp) del: const)
apply (simp (no_asm_simp) del: const)
apply (subst tMap_const_vConc)
  apply (simp (no_asm_simp) del: const)
  apply (rule conjI)
  apply (simp (no_asm_simp))
    apply (subst headers_delH1__reg2, assumption)
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp))
apply (subst tMap_const_vConc)
  apply (simp (no_asm_simp) del: const)
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp) del: const)
  apply (rule conjI)
  apply (simp (no_asm_simp))
    apply (subst headers_delH1__reg2, assumption)
  apply (simp (no_asm_simp))
  apply (rule sym, simp (no_asm_simp))
apply (subst tMap_const_vConc)
  apply (simp (no_asm_simp) del: const)
  apply (rule conjI)
  apply (simp (no_asm_simp))
    apply (subst headers_delH1__reg2, assumption)
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp))
apply (subst tMap_const_vConc)
  apply (simp (no_asm_simp) del: const)
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp) del: const)
  apply (rule conjI)
  apply (simp (no_asm_simp))
    apply (subst headers_delH1__reg2, assumption)
  apply (simp (no_asm_simp))
  apply (rule sym, simp (no_asm_simp))
apply (subst tMap_const_hConc)+
apply (simp (no_asm_simp) del: const)
done

subsection {* Lifting of Inversion Combinators to the Next Dimension *}

text {* The initial inversion operator is @{text "addH2"},
as used in the definition of @{text "inverse1"}.

The first argument @{text "u"} is the contents of ``empty'' cells
created by inversion.

The second argument @{text "h"} converts @{text "u"}
into an update function for @{text "dConc"},
and the third argument @{text "g"} is the
inversion operator of the next-lower dimension.
*}

consts invLift0 ::
  "'a \<Rightarrow>
   ('a \<Rightarrow> ('e,'d) T \<Rightarrow> ('e,'d) T) \<Rightarrow>
   ('a \<Rightarrow>     'b    \<Rightarrow> ('c,'d) T) \<Rightarrow>
   ('a \<Rightarrow> ('e,'b) T \<Rightarrow> ('c,'e,'d) regT2)"

defs invLift0_def:
 "invLift0 u h g h1 ==
  tFold  (% h2 t2 . Abs_regT2 (addH2 h2 (g h1 t2))) (dConc (h u))"

lemma invLift0_addH[simp]:
 "invLift0 u h g h1 (addH h2 t2) = Abs_regT2 (addH2 h2 (g h1 t2))"
by (unfold invLift0_def, simp)

lemma invLift0_addH1[simp]:
 "Rep_regT2 (invLift0 u h g h1 (addH h2 t2)) = addH2 h2 (g h1 t2)"
apply simp
apply (subst Abs_regT2_inverse, rule regT2, simp)
apply (rule conjI, simp_all)
done

lemma reg2dim2_invLift0_addH[simp]:
 "reg2dim2 (invLift0 u h g h1 (addH h2 t2)) = singleton h2"
by simp

lemma cs_invLift0_addH[simp]:
 "\<lbrakk> \<And> u v t . h u (g v t) = g u t \<rbrakk> \<Longrightarrow>
  h u (delH2 (Rep_regT2 (invLift0 u h g h1 (addH h2 t2)))) = g u t2"
apply simp
apply (subst Abs_regT2_inverse, rule regT2, simp)
apply (rule conjI, simp_all)
done

lemma invLift0_hConc[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2)
  \<rbrakk> \<Longrightarrow> invLift0 u h g h1 (hConc t1 t2) =
  dConc (h u) (invLift0 u h g h1 t1) (invLift0 u h g h1 t2)"
by (unfold invLift0_def, simp)

lemma reg2dim2_invLift0:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x t . headers (g x t) = headers t \<rbrakk> \<Longrightarrow>
  reg2dim2 (invLift0 u h g h1 t) = headers t"
apply (unfold invLift0_def, induct_tac t rule: T_induct, simp_all)
apply (fold invLift0_def)
apply (cut_tac x="invLift0 u h g h1 t1" in Rep_regT2)
apply (cut_tac x="invLift0 u h g h1 t2" in Rep_regT2)
apply (subst reg2dim2_dConc)
  apply simp
  apply (simp add: regT2_def)
  apply (drule regularOuter2, erule exE, erule exE, simp)
  apply (rule conjI)
  apply (rule sym, erule regSkelOuter2_eq_Some)
  apply (drule reg2dim2)
  apply (rule sym, assumption)
  apply (simp add: regT2_def)
  apply (rotate_tac -1, drule regularOuter2, erule exE, erule exE, simp)
  apply (rule conjI)
  apply (rule sym, erule regSkelOuter2_eq_Some)
  apply (drule reg2dim2)
  apply (rule sym, assumption)
apply (simp add: Rep_regT2_inverse)
done

lemma regSkelOuter2_invLift0_EX:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t) \<rbrakk> \<Longrightarrow>
  EX hs1 .
  regSkelOuter2 (Rep_regT2 (invLift0 u h g h1 t)) = Some (hs1, headers t)"
apply (unfold invLift0_def, induct_tac t rule: T_induct, simp_all)
apply (subst Abs_regT2_inverse, rule regT2, simp)
  apply (rule conjI)
  apply simp
  apply simp
apply simp
apply (fold invLift0_def)
apply (erule exE, erule exE)
apply (subst regSkelOuter2_dConc1)
  apply simp
  apply assumption
  apply assumption
apply (rule_tac x="append hs1 hs1a" in exI, simp)
done

lemma cs_invLift0_hConc[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2)
  \<rbrakk> \<Longrightarrow>
  h u (delH1 (Rep_regT2 (invLift0 u h g h1 (hConc t1 t2)))) =
  hConc (h u (delH1 (Rep_regT2 (invLift0 u h g h1 t1))))
        (h u (delH1 (Rep_regT2 (invLift0 u h g h1 t2))))"
apply (cut_tac x="invLift0 u h g h1 t1" in Rep_regT2)
apply (cut_tac x="invLift0 u h g h1 t2" in Rep_regT2)
apply (simp add: regT2_def)
apply (drule regularOuter2, erule exE, erule exE)
apply (drule regularOuter2, erule exE, erule exE)
apply (subst cs_dConc [of "h u"])
  apply simp
  apply simp
  apply simp
  apply simp
  apply (rule conjI)
  apply simp
  apply simp
  apply simp
  apply (rule conjI)
  apply simp
  apply simp
apply simp
done

consts invLift ::
  "'a \<Rightarrow>
   ('a \<Rightarrow> ('e,'d) T \<Rightarrow> ('e,'d) T) \<Rightarrow>
   ('a \<Rightarrow>     'b    \<Rightarrow> ('c,'d) T) \<Rightarrow>
   ('a \<Rightarrow> ('e,'b) T \<Rightarrow> ('c,('e,'d) T) T)"

defs invLift_def: "invLift u h g h1 t == Rep_regT2 (invLift0 u h g h1 t)"

lemma invLift_addH[simp]:
  "\<lbrakk> \<And> x y t . headers (g x t) = headers (g y t) \<rbrakk> \<Longrightarrow>
   invLift u h g h1 (addH h2 t2) = addH2 h2 (g h1 t2)"
apply (unfold invLift_def, simp)
apply (subst Abs_regT2_inverse, simp_all add: regT2_def)
apply (rule regularOuter2I, auto)
done

lemma headers_invLift0_invariant:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And>x y t. headers (g x t) = headers (g y t) \<rbrakk> \<Longrightarrow>
  headers (Rep_regT2 (invLift0 u h g x t)) =
  headers (Rep_regT2 (invLift0 u h g y t))"
apply (induct_tac t rule: T_induct)
apply (subst invLift0_addH1)
apply (subst invLift0_addH1)
apply simp
apply simp
done

text {* The following lemma justifies the build-up
for higher-dimensional inversion functions. *}

lemma headers_invLift_invariant:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t) \<rbrakk> \<Longrightarrow>
   headers (invLift u h g x t) = headers (invLift u h g y t)"
apply (unfold invLift_def)
apply (cut_tac x="invLift0 u h g x t" in Rep_regT2)
apply (cut_tac x="invLift0 u h g y t" in Rep_regT2)
apply (unfold regT2_def, simp)
apply (drule regularOuter2, erule exE, erule exE)
apply (drule regularOuter2, erule exE, erule exE)
apply (drule regSkelOuter2_eq_Some)
apply (drule regSkelOuter2_eq_Some)
apply (rule headers_invLift0_invariant)
apply simp_all
done

lemma invLift_hConc[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t);
    regSkelOuter2 (invLift u h g h1 t1) = Some (hs1a, hs2a);
    regSkelOuter2 (invLift u h g h1 t2) = Some (hs1b, hs2b)
   \<rbrakk> \<Longrightarrow>
   invLift u h g h1 (hConc t1 t2) = 
   hConc (vConc (invLift u h g h1 t1)
                (tMap (const (h u (delH1 (invLift u h g h1 t2)))) (invLift u h g h1 t1)))
         (vConc (tMap (const (h u (delH1 (invLift u h g h1 t1)))) (invLift u h g h1 t2))
                (invLift u h g h1 t2))"
apply (unfold invLift_def, simp)
apply (subst dConc2 [THEN sym], auto)
done

lemma regSkelOuter2_invLift_EX:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t) \<rbrakk> \<Longrightarrow>
  EX hs1 . regSkelOuter2 (invLift u h g h1 t) = Some (hs1, headers t)"
apply (unfold invLift_def)
apply (rule regSkelOuter2_invLift0_EX)
apply simp_all
done

lemma delH1_invLift:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t . h u (h u t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t)
  \<rbrakk> \<Longrightarrow>
  delH1 (invLift u h g v t) = tFold (% h0 t0 . addH h0 (delH1 (g v t0))) (hConcU (h u)) t"
apply (induct_tac t rule: T_induct, simp_all del: const)
apply (cut_tac u=u and h=h and g=g and "h1.0"=v and t=t1 in regSkelOuter2_invLift_EX)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (erule exE)
apply (cut_tac u=u and h=h and g=g and "h1.0"=v and t=t2 in regSkelOuter2_invLift_EX)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (erule exE)
apply (subst invLift_hConc)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (simp (no_asm_simp))
apply (subst delH1_vConc)
  apply assumption
  apply (simp (no_asm_simp))
  apply (rule conjI, simp (no_asm_simp), simp (no_asm_simp))
apply (subst delH1_tMap_const)
apply (simp (no_asm_simp))
apply (fold hConcU_def)
apply (cut_tac u="h u" in hConcU_assoc)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (simp del: hConcU_def)
done

lemma h_u_delH1_invLift:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t x . h u (h x t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t);
    \<And> h0 t0 . h u (addH h0 (delH1 (g v t0))) = addH h0 (delH1 (g u t0))
  \<rbrakk> \<Longrightarrow>
  h u (delH1 (invLift u h g v t)) = tFold (% h0 t0 . addH h0 (delH1 (g u t0))) hConc t"
apply (subst delH1_invLift)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (simp (no_asm_simp))
done

lemma headers_h_u_delH1_invLift[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t x . h u (h x t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t);
    \<And> h0 t0 . h u (addH h0 (delH1 (g v t0))) = addH h0 (delH1 (g u t0))
  \<rbrakk> \<Longrightarrow>
  headers (h u (delH1 (invLift u h g v t))) = headers t"
apply (subst h_u_delH1_invLift [of h u g v t])
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (simp (no_asm_simp))
apply (subst headers_def)
apply (simp (no_asm_simp))
done

lemma headers_delH1_invLift[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t x . h u (h x t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t);
    \<And> h0 t0 . h u (addH h0 (delH1 (g v t0))) = addH h0 (delH1 (g u t0))
  \<rbrakk> \<Longrightarrow>
  headers (delH1 (invLift u h g v t)) = headers t"
apply (cut_tac headers_h_u_delH1_invLift [of h u g v t])
  apply simp
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
done

lemma regSkelOuter2_dConcFill:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t x . h u (h x t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t);
    regSkelOuter2 (invLift u h g h1 t1) = Some (hs1a, hs2a);
    regSkelOuter2 (invLift u h g h1 t2) = Some (hs1b, hs2b)
   \<rbrakk> \<Longrightarrow>
  regSkelOuter2 (tMap (const (h u (delH1 (invLift u h g h1 t2))))
              (invLift u h g h1 t1)) = Some (hs1a,hs2b)"
apply (cut_tac "t2.0"="h u (delH1 (invLift u h g h1 t2))" and "t1.0"="invLift u h g h1 t1" in regSkelOuter2_tMap_const)
apply simp
done

lemma headers_invLift_hConc[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t x . h u (h x t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t);
    regSkelOuter2 (invLift u h g h1 t1) = Some (hs1a, hs2a);
    regSkelOuter2 (invLift u h g h1 t2) = Some (hs1b, hs2b)
   \<rbrakk> \<Longrightarrow>
   headers (invLift u h g h1 (hConc t1 t2)) = 
   append (headers (invLift u h g h1 t1))
          (headers (invLift u h g h1 t2))"
apply (subst invLift_hConc)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (cut_tac h=h and u=u and g=g and "h1.0"=h1 and
               "t1.0"=t1 and hs1a=hs1a and hs2a=hs2a and
               "t2.0"=t2 and hs1b=hs1b and hs2b=hs2b in regSkelOuter2_dConcFill)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (cut_tac h=h and u=u and g=g and "h1.0"=h1 and
               "t1.0"=t2 and hs1a=hs1b and hs2a=hs2b and
               "t2.0"=t1 and hs1b=hs1a and hs2b=hs2a in regSkelOuter2_dConcFill)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (simp (no_asm_simp))
apply (subst headers_vConc)
  apply assumption
  apply assumption
apply (subst headers_vConc)
  apply assumption
  apply assumption
apply (simp (no_asm_simp))
done

lemma headers_invLift[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t x . h u (h x t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t)
   \<rbrakk> \<Longrightarrow>
   headers (invLift u h g h1 t) = tFold (% h2 t2 . headers (g h1 t2)) append t"
apply (induct_tac t rule: T_induct, simp)
apply (cut_tac u=u and h=h and g=g and "h1.0"=h1 and t=t1 in regSkelOuter2_invLift_EX)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (erule exE)
apply (cut_tac u=u and h=h and g=g and "h1.0"=h1 and t=t2 in regSkelOuter2_invLift_EX)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (erule exE)
apply (subst headers_invLift_hConc)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (simp (no_asm_simp))
done

lemma regSkelOuter2_invLift[simp]:
 "\<lbrakk> \<And> t . headers (h u t) = headers t;
    \<And> t x . h u (h x t) = h u t;
    \<And> t1 t2 . h u (hConc t1 t2) = hConc (h u t1) (h u t2);
    \<And> x y t . headers (g x t) = headers (g y t);
    \<And> h0 t0 . h u (addH h0 (delH1 (g h1 t0))) = addH h0 (delH1 (g u t0))
   \<rbrakk> \<Longrightarrow>
   regSkelOuter2 (invLift u h g h1 t) =
   Some (tFold (% h2 t2 . headers (g h1 t2)) append t, headers t)"
apply (induct_tac t rule: T_induct, simp)
apply (cut_tac u=u and h=h and g=g and "h1.0"=h1 and t=t1 in regSkelOuter2_invLift_EX)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (erule exE)
apply (cut_tac u=u and h=h and g=g and "h1.0"=h1 and t=t2 in regSkelOuter2_invLift_EX)
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
    apply (erule exE)
apply (subst invLift_hConc)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (subst regSkelOuter2_hConc)
apply (cut_tac h=h and u=u and g=g and "h1.0"=h1 and
               "t1.0"=t1 and hs1a=hs1 and hs2a="headers t1" and
               "t2.0"=t2 and hs1b=hs1a and hs2b="headers t2" in regSkelOuter2_dConcFill)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (cut_tac h=h and u=u and g=g and "h1.0"=h1 and
               "t1.0"=t2 and hs1a=hs1a and hs2a="headers t2" and
               "t2.0"=t1 and hs1b=hs1 and hs2b="headers t1" in regSkelOuter2_dConcFill)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (subst regSkelOuter2_vConc)
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp))
apply (subst regSkelOuter2_vConc)
  apply assumption
  apply (simp (no_asm_simp))
  apply (rule conjI)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (simp (no_asm_simp))
done

subsection {* The Inversion Operator for Two Dimensions *}

consts invOp2 :: "'a \<Rightarrow> 'a \<Rightarrow> ('b,('c,'d) T) T \<Rightarrow> ('c,('b,('a,'d) T) T) T"

defs invOp2_def: "invOp2 u == invLift u slimH2 addH2"

lemma delH1_invOp2:
 "delH1 (invOp2 u v t) = tFold (% h t . addH h (slimH1 v t)) (hConcSH2 u) t"
apply (unfold invOp2_def)
apply (subst delH1_invLift)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (simp del: tFold_hConc hConcU_def slimH2_def)
apply (fold hConcSH2_def)
apply (rule refl)
done

lemma headers_invOp2[simp]:
  "headers (invOp2 u v t) = tFold (% h . headers) append t"
apply (unfold invOp2_def)
apply (subst headers_invLift)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (simp (no_asm_simp))
done

lemma cs_invOp2[simp]:
  "slimH2 u (delH1 (invOp2 u v t)) = tFold (% h t . addH h (slimH1 u t)) hConc t"
apply (subst delH1_invOp2)
apply (induct_tac t rule: T_induct, simp_all del: slimH2_def)
done

lemma regSkelOuter2_invOp2:
  "regSkelOuter2 (invOp2 u h1 t) = Some (tFold (% h . headers) append t, headers t)"
apply (cut_tac u=u and h=slimH2 and g=addH2 and "h1.0"=h1 and t=t in regSkelOuter2_invLift)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (fold invOp2_def)
apply (simp (no_asm_simp))
done

lemma invOp2_hConc[simp]:
  "\<lbrakk>regSkelOuter2 (invOp2 u h1 t1) = Some (hs1a, hs2a);
    regSkelOuter2 (invOp2 u h1 t2) = Some (hs1b, hs2b)
   \<rbrakk> \<Longrightarrow>
   invOp2 u h1 (hConc t1 t2) = 
   hConc (vConc (invOp2 u h1 t1)
                (spread1 hs1a (slimH2 u t2)))
         (vConc (spread1 hs1b (slimH2 u t1))
                (invOp2 u h1 t2))"
apply (unfold invOp2_def, subst invLift_hConc)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply assumption
apply (fold invOp2_def)
apply (subst cs_invOp2)
apply (subst cs_invOp2)
apply (simp (no_asm_simp))
apply (subst tMap_CONST__headers)
apply (subst tMap_CONST__headers)
apply (subst regSkelOuter2_eq_Some [of "invOp2 u h1 t1" hs1a hs2a])
  apply assumption
apply (subst regSkelOuter2_eq_Some [of "invOp2 u h1 t2"])
  apply assumption
apply (fold slimH2_def)
apply (unfold spread1_def)
apply (fold slimH1_def)
apply (simp (no_asm_simp) only: slimH2_as_tFold)
done

subsection {* Two-Dimensional Inversion *}

consts inverse2 :: "'a \<Rightarrow> ('a,('b,('c,'d) T) T) T
                       \<Rightarrow> ('c,('b,('a,'d) T) T) T"

defs inverse2_def: "inverse2 u == tFold (invLift u slimH2 addH2) hConc"

lemma inverse2_addH[simp]: "inverse2 u (addH h t) = invLift u slimH2 addH2 h t"
by (unfold inverse2_def, simp)

lemma inverse2_hConc[simp]:
 "inverse2 u (hConc t1 t2) = hConc (inverse2 u t1) (inverse2 u t2)"
by (unfold inverse2_def, simp)

lemma tFold_tFold_tFold_inverse2:
 "\<lbrakk> assoc c2; assoc c3; assoc c1; assoc c5; assoc c6;
    \<And> h ha hb t . a4 hb (a5 ha (a6 h t)) = a1 h (a2 ha (a3 hb t));
    \<And> h ha t1 t2 .
      c1 (a1 h (a2 ha t1)) (a1 h (a2 ha t2)) = a1 h (a2 ha (c3 t1 t2));
   (* The next two are for tFold_tFold_vConc: *)
    \<And> x y z . a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
    \<And> x1 x2 y1 y2 . c1 (c5 x1 y1) (c5 x2 y2) = c5 (c1 x1 x2) (c1 y1 y2);
   (* units: *)
    \<And> x . LRunit c1 (a1 u x);
    \<And> x y . LRunit c5 (a5 y (a6 u x));
    \<And> x y z . LRunit c1 (a1 z (a5 y (a6 u x)));
   (* finishing 1.2: *)
   \<And> h x1 x2 . c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2)
  \<rbrakk> \<Longrightarrow>
  tFold a4 c1 (tMap (tFold a5 c5 o (tMap (tFold a6 c6))) (inverse2 u t)) =
  tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFold a3 c3))) t)"
apply (induct_tac t rule: T_induct)
txt {* 1: @{text "addH h t0"} *}
apply (induct_tac t0 rule: T_induct)
txt {* 1.1: @{text "t0 = addH ha t0a"} *}
apply (induct_tac t0a rule: T_induct, simp)
txt {* 1.1.2: @{text "t0a = hConc t1 t2"} *}
apply simp
txt {* 1.2: @{text "t0 = hConc t1 t2"} *}
apply (simp del: slimH2_def tFold_tMap)
apply (fold invOp2_def)
apply (cut_tac u=u and "h1.0"=h and t=t1 in regSkelOuter2_invOp2)
apply (cut_tac u=u and "h1.0"=h and t=t2 in regSkelOuter2_invOp2)
apply (subst invOp2_hConc)
  apply assumption
  apply assumption
apply (subgoal_tac "ALL t . tFold a5 c5 (tMap (tFold a6 c6) t) =
          tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 t")
  prefer 2
  apply (rule allI, simp (no_asm_simp))
apply (simp (no_asm_simp)  del: slimH2_def tFold_tMap)
apply (subst tFold_tFold_vConc [of c5 c1 a4])
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
    apply (rule conjI)
    apply (rule refl)
    apply (rule refl)
  apply assumption
  apply (rule refl)
apply (subst tFold_tFold_vConc [of c5 c1 a4])
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp)  del: slimH2_def)
    apply (rule conjI)
    apply (rule refl)
    apply (rule refl)
  apply (rule refl)
apply (simp (no_asm_simp) only: tMap_f_spread1)
apply (simp (no_asm_simp) only: tFold_slimH2 tFold_slimH1)
apply (simp (no_asm_simp) only: f_tFold_const)
apply (simp (no_asm_simp) only: tFold_spread1)
apply (subgoal_tac "(\<lambda>h. a4 h (tFold (\<lambda>h0. tFold (\<lambda>h0a t0. a5 h0 (a6 u t0)) const) c5 t1)) =
   (\<lambda>h. a4 h (tFold (\<lambda>h0. tFold (\<lambda>h0a t0. a5 arbitrary (a6 u arbitrary)) const) c5 t1))")
  prefer 2
  apply (rule ext)
  apply (rule_tac f="a4 ha" in arg_cong)
  apply (rule_tac x=t1 in fun_cong)
  apply (rule_tac x=c5 in fun_cong)
  apply (rule_tac f=tFold in arg_cong)
  apply (rule ext)
  apply (rule fun_cong [of _ _ const])
  apply (rule arg_cong [of _ _ tFold])
  apply (rule ext)
  apply (rule ext)
  apply (cut_tac c=c5 and F="%x . a5 x (a6 u t0)" and x=h0 in LRunit_const)
  apply (simp (no_asm_simp))
  apply (cut_tac c=c5 and F="%x . a5 arbitrary (a6 u x)" and x=t0 in LRunit_const)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (subgoal_tac "(\<lambda>h. a4 h (tFold (\<lambda>h0. tFold (\<lambda>h0a t0. a5 h0 (a6 u t0)) const) c5 t2)) =
   (\<lambda>h. a4 h (tFold (\<lambda>h0. tFold (\<lambda>h0a t0. a5 arbitrary (a6 u arbitrary)) const) c5 t2))")
  prefer 2
  apply (rule ext)
  apply (rule_tac f="a4 ha" in arg_cong)
  apply (rule_tac x=t2 in fun_cong)
  apply (rule_tac x=c5 in fun_cong)
  apply (rule_tac f=tFold in arg_cong)
  apply (rule ext)
  apply (rule fun_cong [of _ _ const])
  apply (rule arg_cong [of _ _ tFold])
  apply (rule ext)
  apply (rule ext)
  apply (cut_tac c=c5 and F="%x . a5 x (a6 u t0)" and x=h0 in LRunit_const)
  apply (simp (no_asm_simp))
  apply (cut_tac c=c5 and F="%x . a5 arbitrary (a6 u x)" and x=t0 in LRunit_const)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
apply (rotate_tac -1, simp (no_asm_simp)  del: slimH2_def tFold_tMap)
apply (thin_tac "ALL t . tFold a5 c5 (tMap (tFold a6 c6) t) =
          tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 t")
apply (subgoal_tac "tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 = (% t . tFold a5 c5 (tMap (tFold a6 c6) t))")
  prefer 2
  apply (rule ext)
  apply (subst tFold_tMap)
  apply assumption
  apply (rule refl)
apply (simp (no_asm_simp) del: tFold_tMap add: o_def)
apply (thin_tac "tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 = (% t . tFold a5 c5 (tMap (tFold a6 c6) t))")
apply (simp (no_asm_simp) add: o_def LRunit_left LRunit_right)
txt {* 2: @{text "t = hConc t1 t2"} *}
apply (simp del: slimH2_def tFold_tMap)
done


lemma tFold_tFold_tFold0_inverse2:
 "\<lbrakk> assoc c2; assoc c3; assoc c1; assoc c5; assoc c6;
    \<And> h ha hb t . a4 hb (a5 ha h) = a1 h (a2 ha hb);
    \<And> h ha t1 t2 .
      c1 (a1 h (a2 ha t1)) (a1 h (a2 ha t2)) = a1 h (a2 ha (c3 t1 t2));
   (* The next two are for tFold_tFold_vConc: *)
    \<And> x y z . a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
    \<And> x1 x2 y1 y2 . c1 (c5 x1 y1) (c5 x2 y2) = c5 (c1 x1 x2) (c1 y1 y2);
   (* units: *)
    \<And> x . LRunit c1 (a1 u x);
    \<And> x y . LRunit c5 (a5 y u);
    \<And> x y z . LRunit c1 (a1 z (a5 y u));
   (* finishing 1.2: *)
   \<And> h x1 x2 . c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2)
  \<rbrakk> \<Longrightarrow>
  tFold a4 c1 (tMap (tFold a5 c5 o (tMap (tFold0 c6))) (inverse2 u t)) =
  tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFold0 c3))) t)"
apply (unfold tFold0_def)
apply (rule tFold_tFold_tFold_inverse2)
apply (simp_all (no_asm_simp))
done

text {* Adapting for cells at lowest level: *}

lemma tFold_tFold_tFoldC_inverse2:
 "\<lbrakk> assoc c1; assoc c2; assoc c3; assoc c5; assoc c6;
    \<And> h ha hb t . a4 hb (a5 ha (a6 h)) = a1 h (a2 ha (a3 hb));
    \<And> h ha t1 t2 .
      c1 (a1 h (a2 ha t1)) (a1 h (a2 ha t2)) = a1 h (a2 ha (c3 t1 t2));
   (* The next two are for tFold_tFold_vConc: *)
    \<And> x y z . a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
    \<And> x1 x2 y1 y2 . c1 (c5 x1 y1) (c5 x2 y2) = c5 (c1 x1 x2) (c1 y1 y2);
   (* units: *)
    \<And> x . LRunit c1 (a1 u x);
    \<And> x y . LRunit c5 (a5 y (a6 u));
    \<And> x y z . LRunit c1 (a1 z (a5 y (a6 u)));
   (* finishing 1.2: *)
   \<And> h x1 x2 . c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2)
  \<rbrakk> \<Longrightarrow>
  tFold a4 c1 (tMap (tFold a5 c5 o (tMap (tFoldC a6 c6))) (inverse2 u t)) =
  tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFoldC a3 c3))) t)"
apply (unfold tFoldC_def)
apply (rule tFold_tFold_tFold_inverse2)
apply assumption+
apply (simp_all (no_asm_simp))
done

lemma tFold_tFold_tFold_inverse2_wrapped:
 "\<lbrakk> assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6;
    \<And> h ha hb t . w2 (a4 hb (a5 ha (a6 h t))) = w1 (a1 h (a2 ha (a3 hb t)));
    \<And> x y . w2 (c4 x y) = c7 (w2 x) (w2 y);
    \<And> x y . c7 (w1 x) (w1 y) = w1 (c1 x y);
    \<And> x y . w2 (c5 x y) = c8 (w2 x) (w2 y);
    \<And> h x y . c7 (w1 (a1 h x)) (w1 (a1 h y)) = w1 (a1 h (c2 x y));
    \<And> h ha x y .
       c7 (w1 (a1 h (a2 ha x))) (w1 (a1 h (a2 ha y))) =
           w1 (a1 h (a2 ha (c3 x y)));
   (* The next two are for tFold_tFold_vConc: *)
    \<And> x y z . a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
    \<And> x1 x2 y1 y2 . c4 (c5 x1 y1) (c5 x2 y2) = c5 (c4 x1 x2) (c4 y1 y2);
   (* units: *)
    \<And> x . LRunit c8 (w1 (a1 u x));
    \<And> x y . LRunit c5 (a5 y (a6 u x));
    \<And> x y z . LRunit c4 (a4 z (a5 y (a6 u x)));
   (* finishing 1.2: *)
   \<And> h x1 x2 . c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2)
  \<rbrakk> \<Longrightarrow>
  w2 (tFold a4 c4 (tMap (tFold a5 c5 o (tMap (tFold a6 c6))) (inverse2 u t))) =
  w1 (tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFold a3 c3))) t))"
apply (induct_tac t rule: T_induct)
txt {* 1: @{text "addH h t0"} *}
apply (induct_tac t0 rule: T_induct)
txt {* 1.1: @{text "t0 = addH ha t0a"} *}
apply (induct_tac t0a rule: T_induct, simp (no_asm_simp))
txt {* 1.1.2: @{text "t0a = hConc t1 t2"} *}
apply simp
txt {* 1.2: @{text "t0 = hConc t1 t2"} *}
apply (simp del: slimH2_def tFold_tMap)
apply (fold invOp2_def)
apply (cut_tac u=u and "h1.0"=h and t=t1 in regSkelOuter2_invOp2)
apply (cut_tac u=u and "h1.0"=h and t=t2 in regSkelOuter2_invOp2)
apply (subst invOp2_hConc)
  apply assumption
  apply assumption
apply (subgoal_tac "ALL t . tFold a5 c5 (tMap (tFold a6 c6) t) =
          tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 t")
  prefer 2
  apply (rule allI, simp (no_asm_simp))
apply (simp (no_asm_simp)  del: slimH2_def tFold_tMap)
apply (subst tFold_tFold_vConc [of c5 c4 a4])
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
    apply (rule conjI, rule refl, rule refl)
  apply assumption
  apply (rule refl)
apply (subst tFold_tFold_vConc [of c5 c4 a4])
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp)  del: slimH2_def)
    apply (rule conjI, rule refl, rule refl)
  apply (rule refl)
apply (simp (no_asm_simp) only: tMap_f_spread1)
apply (simp (no_asm_simp) only: tFold_slimH2 tFold_slimH1)
apply (simp (no_asm_simp) only: f_tFold_const)
apply (subgoal_tac "(\<lambda>h0 . tFold (\<lambda>h0a t0 . a5 h0 (a6 u t0)) const) = (\<lambda> h0 t0 . a5 arbitrary (a6 u arbitrary))")
  prefer 2
  apply (subgoal_tac "(\<lambda>h0 . tFold (\<lambda>h0a t0 . a5 h0 (a6 u t0)) const) = (\<lambda>h0 . tFold (\<lambda> h0 t0 . a5 arbitrary (a6 u arbitrary)) const)")
    prefer 2
    apply (rule ext)
    apply (rule_tac x=const in fun_cong)
    apply (rule_tac f=tFold in arg_cong)
    apply (rule ext)
    apply (rule ext)
    apply (cut_tac c=c5 and F="%x . a5 x (a6 u t0)" and x=h0 in LRunit_const)
      apply (simp (no_asm_simp))
    apply (cut_tac c=c5 and F="%x . a5 arbitrary (a6 u x)" and x=t0 in LRunit_const)
      apply (simp (no_asm_simp))
    apply (simp (no_asm_simp))
  apply (rotate_tac -1, erule trans)
  apply (rule ext)
  apply (rule ext)
  apply (simp (no_asm_simp))
apply (rotate_tac -1, erule ssubst)
apply (simp (no_asm_simp)  del: slimH2_def tFold_tMap)
apply (simp (no_asm_simp) only: tFold_spread1)
apply (subst foldr1_map1_LRunit)
  apply (simp (no_asm_simp))
  apply assumption
apply (subst foldr1_map1_LRunit)
  apply (simp (no_asm_simp))
  apply assumption
apply (thin_tac "ALL t . tFold a5 c5 (tMap (tFold a6 c6) t) =
          tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 t")
apply (subgoal_tac "tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 = (% t . tFold a5 c5 (tMap (tFold a6 c6) t))")
  prefer 2
  apply (rule ext)
  apply (subst tFold_tMap)
  apply assumption
  apply (rule refl)
apply (simp (no_asm_simp) del: tFold_tMap add: LRunit_left LRunit_right)
txt {* 2: @{text "t = hConc t1 t2"} *}
apply (simp del: slimH2_def tFold_tMap)
done

lemma tFold_tFold_tFoldC_inverse2_wrapped:
 "\<lbrakk> assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6;
    \<And> h ha hb t . w2 (a4 hb (a5 ha (a6 h))) = w1 (a1 h (a2 ha (a3 hb)));
    \<And> x y . w2 (c4 x y) = c7 (w2 x) (w2 y);
    \<And> x y . c7 (w1 x) (w1 y) = w1 (c1 x y);
    \<And> x y . w2 (c5 x y) = c8 (w2 x) (w2 y);
    \<And> h x y . c7 (w1 (a1 h x)) (w1 (a1 h y)) = w1 (a1 h (c2 x y));
    \<And> h ha x y .
       c7 (w1 (a1 h (a2 ha x))) (w1 (a1 h (a2 ha y))) =
           w1 (a1 h (a2 ha (c3 x y)));
   (* The next two are for tFold_tFold_vConc: *)
    \<And> x y z . a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
    \<And> x1 x2 y1 y2 . c4 (c5 x1 y1) (c5 x2 y2) = c5 (c4 x1 x2) (c4 y1 y2);
   (* units: *)
    \<And> x . LRunit c8 (w1 (a1 u x));
    \<And> x y . LRunit c5 (a5 y (a6 u));
    \<And> x y z . LRunit c4 (a4 z (a5 y (a6 u)));
   (* finishing 1.2: *)
   \<And> h x1 x2 . c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2)
  \<rbrakk> \<Longrightarrow>
  w2 (tFold a4 c4 (tMap (tFold a5 c5 o (tMap (tFoldC a6 c6))) (inverse2 u t))) =
  w1 (tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFoldC a3 c3))) t))"
apply (unfold tFoldC_def)
apply (rule tFold_tFold_tFold_inverse2_wrapped)
apply assumption+
apply (simp_all (no_asm_simp))
apply simp_all
txt {* Strange: Why doesn't the first @{text "simp_all"},
 even without @{text "no_asm_simp"}, go through? *}
done

lemma wrapped_tFold:
  "\<lbrakk> assoc c4; assoc c7; \<And> x y . w2 (c4 x y) = c7 (w2 x) (w2 y) \<rbrakk> \<Longrightarrow>
   w2 (tFold a4 c4 t) = tFold (% h t . w2 (a4 h t)) c7 t"
by (induct_tac t rule: T_induct, simp_all)

lemma wrapped_foldr1:
  "\<lbrakk> assoc c5; assoc c8; \<And> x y . f (c5 x y) = c8 (f x) (f y) \<rbrakk> \<Longrightarrow>
   f (foldr1 c5 xs) = foldr1 c8 (map1 f xs)"
by (induct_tac xs rule: neList_append_induct, simp_all)

lemma wrapped2_tFold:
  "\<lbrakk> assoc c5; assoc c7;
    \<And> h x y . w2 (a4 h (c5 x y)) = c7 (w2 (a4 h x)) (w2 (a4 h y)) \<rbrakk> \<Longrightarrow>
   (% x . w2 (a4 x (tFold a8 c5 t))) = (% x . tFold (% h t . w2 (a4 x (a8 h t))) c7 t)"
apply (rule ext)
apply (rule wrapped_tFold [of c5 c7])
  apply assumption
  apply assumption
  apply (simp_all (no_asm_simp))
done

lemma tFold_tFold_tFold_inverse2_gen:
 "\<lbrakk> assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6; assoc c7;
    \<And> h ha hb t . w2 (a4 hb (a5 ha (a6 h t))) = w1 (a1 h (a2 ha (a3 hb t)));
    (* finishing 2, and influencing the next rule: *)
    \<And> x y . c7 (w1 x) (w1 y) = w1 (c1 x y);
    (* finishing 1.1.2 *)
    \<And> h ha x y .
       w1 (c1 (a1 h (a2 ha x)) (a1 h (a2 ha y))) =
           w1 (a1 h (a2 ha (c3 x y)));
   (* The next few are for tFold_tFold_vConc_wrapped: *)
    \<And> h x y . w2 (a4 h (c5 x y)) = w2 (c4 (a4 h x) (a4 h y));
    \<And> x y . w2 (c4 x y) = c7 (w2 x) (w2 y);
    \<And> x1 x2 y1 y2 . c7 (w2 (c4 x1 x2)) (w2 (c4 y1 y2)) =
                         w2 (c4 (c4 x1 y1) (c4 x2 y2));
(* stronger:
    \<And> x1 x2 y1 y2 . c4 (c4 x1 x2) (c4 y1 y2) =
                     c4 (c4 x1 y1) (c4 x2 y2);
*)
   (* units: *)
(*
    \<And> x y . LRunit c5 (a5 y (a6 u x));
    \<And> h x y . LRunit c4 (a4 h (a5 y (a6 u x)));
*)
    \<And> x . LRunit c7 (w1 (a1 u x));
    (* finishing 1.2: *)
    \<And> h x y . w1 (c1 (a1 h x) (a1 h y)) = w1 (a1 h (c2 x y))
  \<rbrakk> \<Longrightarrow>
  w2 (tFold a4 c4 (tMap (tFold a5 c5 o (tMap (tFold a6 c6))) (inverse2 u t))) =
  w1 (tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFold a3 c3))) t))"
apply (induct_tac t rule: T_induct)
txt {* 1: @{text "addH h t0"} *}
apply (induct_tac t0 rule: T_induct)
txt {* 1.1: @{text "t0 = addH ha t0a"} *}
apply (induct_tac t0a rule: T_induct, simp (no_asm_simp))
txt {* 1.1.2: @{text "t0a = hConc t1 t2"} *}
apply simp
txt {* 1.2: @{text "t0 = hConc t1 t2"} *} (*
apply (tactic "thin_tac \"!! x y. c7 (w1 x) (w1 y) = w1 (c1 x y)\" 1")
-- doesn't work. Why?
*)
apply (simp del: slimH2_def tFold_tMap)
apply (fold invOp2_def)
apply (cut_tac u=u and "h1.0"=h and t=t1 in regSkelOuter2_invOp2)
apply (cut_tac u=u and "h1.0"=h and t=t2 in regSkelOuter2_invOp2)
apply (subst invOp2_hConc)
  apply assumption
  apply assumption
apply (subgoal_tac "ALL t . tFold a5 c5 (tMap (tFold a6 c6) t) =
          tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 t")
  prefer 2
  apply (rule allI, simp (no_asm_simp))
apply (simp (no_asm_simp)  del: slimH2_def tFold_tMap)
apply (subst tFold_tFold_vConc_wrapped [of c4 c5 c4 w2 a4 w2 a4 c7])
  apply assumption
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
    apply (rule conjI, rule refl, rule refl)
  apply assumption
apply (subst tFold_tFold_vConc_wrapped [of c4 c5 c4 w2 a4 w2 a4 c7])
  apply assumption
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp))
  apply assumption
  apply (simp (no_asm_simp)  del: slimH2_def)
apply (simp (no_asm_simp) only: spread1_slimH2)
apply (simp (no_asm_simp) only: tMap_f_slimH3 tFold_slimH2 tFold_slimH1)
apply (subst tFold_tMap [of _ _ "(tFold (\<lambda>h0 t0. a5 h0 (tFold (\<lambda>h0. a6 u) const t0)) c5)"])
  apply assumption
apply (subst tFold_tMap [of _ _ "(tFold (\<lambda>h0 t0. a5 h0 (tFold (\<lambda>h0. a6 u) const t0)) c5)"])
  apply assumption
apply (subst wrapped_tFold [of c4 c7 w2 "(\<lambda>h t0. a4 h (tFold (\<lambda>h0 t0. a5 h0 (tFold (\<lambda>h0. a6 u) const t0)) c5 t0))"])
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
apply (subst wrapped_tFold [of c4 c7 w2 "(\<lambda>h t0. a4 h (tFold (\<lambda>h0 t0. a5 h0 (tFold (\<lambda>h0. a6 u) const t0)) c5 t0))"])
  apply assumption
  apply assumption
  apply (simp (no_asm_simp))
apply (subgoal_tac "(\<lambda>h t. w2 (a4 h (tFold (\<lambda>h0 t0. a5 h0 (tFold (\<lambda>h0. a6 u) const t0)) c5 t))) = (\<lambda> h t . w1 (a1 u arbitrary))")
  prefer 2
  apply (rule ext)
  apply (rule ext)
  apply (cut_tac "c4.0"=c5 and "c7.0"=c7 and "w2.0"="%z . w2 (a4 ha z)" in wrapped_tFold)
    apply assumption
    apply assumption
    apply (simp (no_asm_simp))
  apply (rotate_tac -1, erule ssubst)
  apply (simp (no_asm_simp) only: f_tFold_const)
  apply (cut_tac c=c7 and a="(\<lambda>h. tFold (\<lambda>h0 t0. w1 (a1 u (a2 h (a3 ha t0)))) const)" in tFold_LRunit)
  apply (simp (no_asm_simp))
  apply (simp (no_asm_simp) only: f_tFold_const)
  apply (simp (no_asm_simp) only: tFold_const_const)
    apply assumption
  apply (rotate_tac -1, erule ssubst)
  apply (subgoal_tac "tFold (\<lambda>h0 t0. w1 (a1 u (a2 arbitrary (a3 ha t0)))) const = tFold (\<lambda>h0 t0. w1 (a1 u arbitrary)) const")
  apply (rotate_tac -1, erule ssubst)
  apply (simp (no_asm_simp) only: tFold_const_const)
    apply (rule_tac x=const in fun_cong)
    apply (rule_tac f=tFold in arg_cong)
    apply (rule ext)
    apply (rule ext)
    apply (rule_tac c=c7 and F="%x . w1 (a1 u x)" in LRunit_const)
      apply (simp (no_asm_simp))
apply (rotate_tac -1, erule ssubst)
apply (simp (no_asm_simp)  del: slimH2_def tFold_tMap)
apply (thin_tac "ALL t . tFold a5 c5 (tMap (tFold a6 c6) t) =
          tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 t")
apply (subgoal_tac "tFold (\<lambda>h t0. a5 h (tFold a6 c6 t0)) c5 = (% t . tFold a5 c5 (tMap (tFold a6 c6) t))")
  prefer 2
  apply (rule ext)
  apply (subst tFold_tMap)
  apply assumption
  apply (rule refl)
apply (simp (no_asm_simp) del: tFold_tMap add: LRunit_left LRunit_right)
txt {* Now we expand some extra effort to be able to work with a single, wrapped-only unit assumption. *}
apply (subgoal_tac "w1 (c1 (a1 h (tFold a2 c2 (tMap (tFold a3 c3) t1)))
               (c1 (a1 u arbitrary)
                 (c1 (a1 u arbitrary)
                   (a1 h (tFold a2 c2 (tMap (tFold a3 c3) t2)))))) =
     c7 (w1 (a1 h (tFold a2 c2 (tMap (tFold a3 c3) t1))))
    (c7 (w1 (a1 u arbitrary))
    (c7 (w1 (a1 u arbitrary))
        (w1 (a1 h (tFold a2 c2 (tMap (tFold a3 c3) t2))))))")
  prefer 2
  apply (simp (no_asm_simp))
apply (rotate_tac -1, erule trans)
apply (subst LRunit_left [of c7 "w1 (a1 u arbitrary)"])
  apply (simp (no_asm_simp))
apply (subst LRunit_left [of c7 "w1 (a1 u arbitrary)"])
  apply (simp (no_asm_simp))
apply (simp (no_asm_simp))
txt {* 2: @{text "t = hConc t1 t2"} *}
apply (simp del: slimH2_def tFold_tMap)
done

lemma tFold_tFold_tFoldC_inverse2_gen:
 "\<lbrakk> assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6; assoc c7;
    \<And> h ha hb . w2 (a4 hb (a5 ha (a6 h))) = w1 (a1 h (a2 ha (a3 hb)));
    (* finishing 2, and influencing the next rule: *)
    \<And> x y . c7 (w1 x) (w1 y) = w1 (c1 x y);
    (* finishing 1.1.2 *)
    \<And> h ha x y .
       w1 (c1 (a1 h (a2 ha x)) (a1 h (a2 ha y))) =
           w1 (a1 h (a2 ha (c3 x y)));
   (* The next few are for tFold_tFold_vConc_wrapped: *)
    \<And> h x y . w2 (a4 h (c5 x y)) = w2 (c4 (a4 h x) (a4 h y));
    \<And> x y . w2 (c4 x y) = c7 (w2 x) (w2 y);
    \<And> x1 x2 y1 y2 . c7 (w2 (c4 x1 x2)) (w2 (c4 y1 y2)) =
                         w2 (c4 (c4 x1 y1) (c4 x2 y2));
(* stronger:
    \<And> x1 x2 y1 y2 . c4 (c4 x1 x2) (c4 y1 y2) =
                     c4 (c4 x1 y1) (c4 x2 y2);
*)
   (* units: *)
(*
    \<And> x y . LRunit c5 (a5 y (a6 u));
    \<And> h x y . LRunit c4 (a4 h (a5 y (a6 u)));
*)
    \<And> x . LRunit c7 (w1 (a1 u x));
    (* finishing 1.2: *)
    \<And> h x y . w1 (c1 (a1 h x) (a1 h y)) = w1 (a1 h (c2 x y))
  \<rbrakk> \<Longrightarrow>
  w2 (tFold a4 c4 (tMap (tFold a5 c5 o (tMap (tFoldC a6 c6))) (inverse2 u t))) =
  w1 (tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFoldC a3 c3))) t))"
apply (unfold tFoldC_def)
apply (rule tFold_tFold_tFold_inverse2_gen)
apply assumption+
apply (simp_all (no_asm_simp))
apply simp
apply (subgoal_tac "c7 (c7 (w2 x1) (w2 x2)) (c7 (w2 y1) (w2 y2)) =
                    c7 (w2 (c4 x1 x2)) (w2 (c4 y1 y2))")
  prefer 2
  apply (simp (no_asm_simp))
apply simp
done


lemma id_tFold_tFold_tFoldC_inverse2_gen:
 "\<lbrakk> assoc c1; assoc c2; assoc c3; assoc c5; assoc c6;
    \<And> h ha hb . a4 hb (a5 ha (a6 h)) = a1 h (a2 ha (a3 hb));
    (* finishing 1.1.2 *)
    \<And> h ha x y .
       c1 (a1 h (a2 ha x)) (a1 h (a2 ha y)) = a1 h (a2 ha (c3 x y));
   (* The next few are for tFold_tFold_vConc_wrapped: *)
    \<And> h x y . a4 h (c5 x y) = c1 (a4 h x) (a4 h y);
    \<And> x1 x2 y1 y2 . c1 (c1 x1 x2) (c1 y1 y2) =
                     c1 (c1 x1 y1) (c1 x2 y2);
   (* units: *)
    \<And> x . LRunit c1 (a1 u x);
    (* finishing 1.2: *)
    \<And> h x y . c1 (a1 h x) (a1 h y) = a1 h (c2 x y)
  \<rbrakk> \<Longrightarrow>
  id (tFold a4 c1 (tMap (tFold a5 c5 o (tMap (tFoldC a6 c6))) (inverse2 u t))) =
  id (tFold a1 c1 (tMap (tFold a2 c2 o (tMap (tFoldC a3 c3))) t))"
apply (rule tFold_tFold_tFoldC_inverse2_gen)
apply assumption+
apply (simp_all (no_asm_simp))
apply (subgoal_tac "a1 h (c2 (a2 ha x) (a2 ha y)) = c1 (a1 h (a2 ha x)) (a1 h (a2 ha y))")
  prefer 2
  apply simp
apply (erule trans)
apply (rotate_tac -1, simp)
done

end


One-Dimensional Inversion

lemma inverse1_addH:

  inverse1 (addH h t) = addH2 h t

lemma inverse1_hConc:

  inverse1 (hConc t1 t2) = hConc (inverse1 t1) (inverse1 t2)

lemma tFold_tFold_inverse1:

  [| assoc c2; assoc c4; !!h2 h1 t. a2 h2 (a1 h1 t) = a3 h1 (a4 h2 t);
     !!h t u. a3 h (c4 t u) = c2 (a3 h t) (a3 h u) |]
  ==> tFold a2 c2 (tMap (tFold a1 c1) (inverse1 t)) =
      tFold a3 c2 (tMap (tFold a4 c4) t)

lemma tFold_tFold0_inverse1:

  [| assoc c2; assoc c4; !!h t u. a2 (c4 t u) h = c2 (a2 t h) (a2 u h) |]
  ==> tFold a2 c2 (tMap (tFold0 c1) (inverse1 t)) =
      tFold (flip a2) c2 (tMap (tFold0 c4) t)

spread1

lemma regSkelOuter2_spread1:

  regSkelOuter2 (spread1 hs t) = Some (hs, headers t)

lemma spread1_singleton:

  spread1 (singleton h) t = addH h t

lemma spread1_append:

  spread1 (append hs1 hs2) t = hConc (spread1 hs1 t) (spread1 hs2 t)

lemma spread1_tFold_append:

  spread1 (tFold f append t1) t = tFold (%h0 t0. spread1 (f h0 t0) t) hConc t1

lemma spread1_hConc_0:

  ALL t1. spread1 hs (hConc t1 t2) = vConc (spread1 hs t1) (spread1 hs t2)

lemma spread1_hConc:

  spread1 hs (hConc t1 t2) = vConc (spread1 hs t1) (spread1 hs t2)

lemma tMap_f_spread1:

  tMap f (spread1 hs t) = spread1 hs (f t)

lemma tFold_spread1:

  assoc c ==> tFold a c (spread1 hs t) = foldr1 c (map1 (%h. a h t) hs)

spread2

lemma spread2_singleton:

  spread2 (singleton h) t = addH2 h t

lemma spread2_append:

  spread2 (append hs1 hs2) t = vConc (spread2 hs1 t) (spread2 hs2 t)

lemma spread2_cons1:

  spread2 (cons1 h hs) t = vCons (h, t) (spread2 hs t)

lemma headers_spread2:

  headers (spread2 hs t) = headers t

lemma regSkelOuter2_spread2_0:

  ALL hs2. regSkelOuter2 (spread2 hs2 t) = Some (headers t, hs2)

lemma regSkelOuter2_spread2:

  regSkelOuter2 (spread2 hs2 t) = Some (headers t, hs2)

lemma spread2_hConc_0:

  ALL t1 t2. spread2 hs2 (hConc t1 t2) = hConc (spread2 hs2 t1) (spread2 hs2 t2)

lemma spread2_hConc:

  spread2 hs2 (hConc t1 t2) = hConc (spread2 hs2 t1) (spread2 hs2 t2)

lemma spread2_addH:

  spread2 hs (addH h t) = addH h (foldr1 hConc (map1 (%h2. addH h2 t) hs))

lemma spread2_tFold_hConc:

  spread2 hs2 (tFold a hConc t) = tFold (%h t. spread2 hs2 (a h t)) hConc t

lemma tMap_tFold_spread2:

  assoc c
  ==> tMap (tFold a c) (spread2 hs t) =
      tMap (%t0. foldr1 c (map1 (%h2. a h2 t0) hs)) t

delH1

lemma delH1_hConc:

  delH1 (hConc t1 t2) = delH1 t1

lemma delH1_addH:

  delH1 (addH h t) = t

lemma delH1_hCons:

  delH1 (hCons (h, t0) t) = t0

lemma delH1_tFold_hConc:

  delH1 (tFold f hConc t) = delH1 (uncurry f (hHead t))

lemma headers_delH1__reg2_0:

  ALL hs1 hs2. regSkelOuter2 t1 = Some (hs1, hs2) --> headers (delH1 t1) = hs2

lemma headers_delH1__reg2:

  regSkelOuter2 t1 = Some (hs1, hs2) ==> headers (delH1 t1) = hs2

lemma delH1_addH2:

  delH1 (addH2 h t) = addH h (delH1 t)

lemma delH1_vConc_0:

  ALL hs1a hs1b hs2a hs2b.
     regSkelOuter2 t1 = Some (hs1a, hs1b) -->
     regSkelOuter2 t2 = Some (hs2a, hs2b) -->
     delH1 (vConc t1 t2) = hConc (delH1 t1) (delH1 t2)

lemma delH1_vConc:

  [| regSkelOuter2 t1 = Some (hs1a, hs1b); regSkelOuter2 t2 = Some (hs2a, hs2b) |]
  ==> delH1 (vConc t1 t2) = hConc (delH1 t1) (delH1 t2)

lemma delH1_tMap_const:

  delH1 (tMap (const t2) t1) = t2

lemma delH1_tMap_CONST:

  delH1 (tMap (%x. t2) t1) = t2

delH2

lemma delH2_hConc:

  delH2 (hConc t1 t2) = hConc (delH2 t1) (delH2 t2)

lemma delH2_addH:

  delH2 (addH h t) = addH h (delH1 t)

lemma delH2_hCons:

  delH2 (hCons (h, t0) t) = hCons (h, delH1 t0) (delH2 t)

lemma delH2_addH2:

  delH2 (addH2 h t) = t

lemma headers_delH2:

  headers (delH2 t) = headers t

lemma delH2_vConc_0:

  ALL hs1 hs2a t2 hs2b.
     regSkelOuter2 t1 = Some (hs1, hs2a) -->
     regSkelOuter2 t2 = Some (hs1, hs2b) --> delH2 (vConc t1 t2) = delH2 t1

lemma delH2_vConc:

  [| regSkelOuter2 t1 = Some (hs1, hs2a); regSkelOuter2 t2 = Some (hs1, hs2b) |]
  ==> delH2 (vConc t1 t2) = delH2 t1

lemma delH2_spread2:

  delH2 (spread2 hs t) = t

lemma delH2_tMap_const:

  delH2 (tMap (const t2) t1) = tMap (const (delH1 t2)) t1

lemma delH2_tMap_CONST:

  delH2 (tMap (%x. t2) t1) = tMap (const (delH1 t2)) t1

Third Dimension Operators

lemma delH1_addH3:

  delH1 (addH3 h t) = addH2 h (delH1 t)

Slimming Operators

lemma tFold_slimH1:

  assoc c ==> tFold a c (slimH1 u t) = tFold (%h0. a u) const t

lemma headers_slimH1:

  headers (slimH1 u t) = singleton u

lemma slimH2_tMap:

  slimH2 h2 = tMap (slimH1 h2)

lemma slimH2_slimH2:

  slimH2 u (slimH2 v t) = slimH2 u t

lemma slimH2_addH:

  slimH2 u (addH h t) = addH h (slimH1 u t)

lemma slimH2_hConc:

  slimH2 u (hConc t1 t2) = hConc (slimH2 u t1) (slimH2 u t2)

lemma slimH2_as_tFold:

  tFold (%h t. addH h (slimH1 u t)) hConc t = slimH2 u t

lemma slimH2_addH2:

  slimH2 u (addH2 h2 t) = addH2 u t

lemma headers_slimH2:

  headers (slimH2 u t) = headers t

lemma regSkelOuter2_slimH2:

  regSkelOuter2 (slimH2 u t) = Some (headers t, singleton u)

lemma slimH2_tFold_hConc:

  slimH2 u (tFold f hConc t) = tFold (%h t. slimH2 u (f h t)) hConc t

lemma slimH2_tFold_addH2_hConc:

  slimH2 u (tFold (%h. addH2 v) hConc t) = tFold (%h. addH2 u) hConc t

lemma del1_slimH2_isConst:

  delH1 (slimH2 u t1) = delH1 (slimH2 u t2)

lemma tFold_slimH2:

  assoc c ==> tFold a c (slimH2 u t) = tFold (%h0 t0. a h0 (slimH1 u t0)) c t

lemma slimH3_expand:

  slimH3 u t = addH3 u (delH3 t)

lemma slimH3_addH:

  slimH3 u (addH h t) = addH h (slimH2 u t)

lemma slimH3_hConc:

  slimH3 u (hConc t1 t2) = hConc (slimH3 u t1) (slimH3 u t2)

lemma spread1_slimH2:

  spread1 hs (slimH2 u t) = slimH3 u (spread1 hs t)

lemma tFold_slimH3:

  assoc c ==> tFold a c (slimH3 u t) = tFold (%h0 t0. a h0 (slimH2 u t0)) c t

lemma tMap_f_slimH3:

  tMap f (slimH3 u t) = tMap (%t0. f (slimH2 u t0)) t

Right-Updating Horizontal Concatenation

lemma hConcU_assoc:

  [| !!t. u (u t) = u t; !!t1 t2. u (hConc t1 t2) = hConc (u t1) (u t2) |]
  ==> assoc (hConcU u)

lemma U_hConcU:

  [| !!t. u (u t) = u t; !!t1 t2. u (hConc t1 t2) = hConc (u t1) (u t2) |]
  ==> u (hConcU u t1 t2) = hConc (u t1) (u t2)

lemma U_tFold_hConcU:

  [| !!t. u (u t) = u t; !!t1 t2. u (hConc t1 t2) = hConc (u t1) (u t2) |]
  ==> u (tFold f (hConcU u) t) = tFold (%h0 t0. u (f h0 t0)) hConc t

lemma hConcSH2_assoc:

  assoc (hConcSH2 u)

lemma slimH2_hConcSH2:

  slimH2 u (hConcSH2 u t1 t2) = hConc (slimH2 u t1) (slimH2 u t2)

lemma slimH2_tFold_hConcSH2:

  slimH2 u (tFold f (hConcSH2 u) t) = tFold (%h t. slimH2 u (f h t)) hConc t

Diagonal Table Concatenation

lemma dConc:

  [| regSkelOuter2 t1 = Some (cs1, hs1); regSkelOuter2 t2 = Some (cs2, hs2) |]
  ==> dConc h (Abs_regT2 t1) (Abs_regT2 t2) =
      Abs_regT2
       (hConc (vConc t1 (tMap (const (h (delH1 t2))) t1))
         (vConc (tMap (const (h (delH1 t1))) t2) t2))

lemma dConc1:

  [| regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2) |]
  ==> dConc h t1 t2 =
      Abs_regT2
       (hConc
         (vConc (Rep_regT2 t1)
           (tMap (const (h (delH1 (Rep_regT2 t2)))) (Rep_regT2 t1)))
         (vConc (tMap (const (h (delH1 (Rep_regT2 t1)))) (Rep_regT2 t2))
           (Rep_regT2 t2)))

lemma regSkelOuter2_dConcDef:

  [| !!t. headers (h t) = headers t; regSkelOuter2 t1 = Some (cs1, hs1);
     regSkelOuter2 t2 = Some (cs2, hs2) |]
  ==> regSkelOuter2
       (hConc (vConc t1 (tMap (const (h (delH1 t2))) t1))
         (vConc (tMap (const (h (delH1 t1))) t2) t2)) =
      Some (append cs1 cs2, append hs1 hs2)

lemma regSkelOuter2_dConc:

  [| !!t. headers (h t) = headers t; regSkelOuter2 t1 = Some (cs1, hs1);
     regSkelOuter2 t2 = Some (cs2, hs2) |]
  ==> regSkelOuter2 (Rep_regT2 (dConc h (Abs_regT2 t1) (Abs_regT2 t2))) =
      Some (append cs1 cs2, append hs1 hs2)

lemma dConc2:

  [| !!t. headers (h t) = headers t;
     regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2) |]
  ==> Rep_regT2 (dConc h t1 t2) =
      hConc
       (vConc (Rep_regT2 t1)
         (tMap (const (h (delH1 (Rep_regT2 t2)))) (Rep_regT2 t1)))
       (vConc (tMap (const (h (delH1 (Rep_regT2 t1)))) (Rep_regT2 t2))
         (Rep_regT2 t2))

lemma regSkelOuter2_dConc1:

  [| !!t. headers (h t) = headers t;
     regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2) |]
  ==> regSkelOuter2 (Rep_regT2 (dConc h t1 t2)) =
      Some (append cs1 cs2, append hs1 hs2)

lemma headers_dConc:

  (!!t. headers (h t) = headers t)
  ==> headers (Rep_regT2 (dConc h t1 t2)) =
      append (headers (Rep_regT2 t1)) (headers (Rep_regT2 t2))

lemma reg2dim2_dConc:

  [| !!t. headers (h t) = headers t;
     regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2) |]
  ==> reg2dim2 (dConc h t1 t2) = append hs1 hs2

lemma cs_dConc:

  [| !!t. headers (h t) = headers t; !!t. h (h t) = h t;
     !!t1 t2. h (hConc t1 t2) = hConc (h t1) (h t2);
     regSkelOuter2 (Rep_regT2 t1) = Some (cs1, hs1);
     regSkelOuter2 (Rep_regT2 t2) = Some (cs2, hs2) |]
  ==> h (delH1 (Rep_regT2 (dConc h t1 t2))) =
      hConc (h (delH1 (Rep_regT2 t1))) (h (delH1 (Rep_regT2 t2)))

lemma dConc_assoc:

  [| !!t. headers (h t) = headers t; !!t. h (h t) = h t;
     !!t1 t2. h (hConc t1 t2) = hConc (h t1) (h t2) |]
  ==> assoc (dConc h)

Lifting of Inversion Combinators to the Next Dimension

lemma invLift0_addH:

  invLift0 u h g h1 (addH h2 t2) = Abs_regT2 (addH2 h2 (g h1 t2))

lemma invLift0_addH1:

  Rep_regT2 (invLift0 u h g h1 (addH h2 t2)) = addH2 h2 (g h1 t2)

lemma reg2dim2_invLift0_addH:

  reg2dim2 (invLift0 u h g h1 (addH h2 t2)) = singleton h2

lemma cs_invLift0_addH:

  (!!u v t. h u (g v t) = g u t)
  ==> h u (delH2 (Rep_regT2 (invLift0 u h g h1 (addH h2 t2)))) = g u t2

lemma invLift0_hConc:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2) |]
  ==> invLift0 u h g h1 (hConc t1 t2) =
      dConc (h u) (invLift0 u h g h1 t1) (invLift0 u h g h1 t2)

lemma reg2dim2_invLift0:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x t. headers (g x t) = headers t |]
  ==> reg2dim2 (invLift0 u h g h1 t) = headers t

lemma regSkelOuter2_invLift0_EX:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t) |]
  ==> EX hs1.
         regSkelOuter2 (Rep_regT2 (invLift0 u h g h1 t)) = Some (hs1, headers t)

lemma cs_invLift0_hConc:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2) |]
  ==> h u (delH1 (Rep_regT2 (invLift0 u h g h1 (hConc t1 t2)))) =
      hConc (h u (delH1 (Rep_regT2 (invLift0 u h g h1 t1))))
       (h u (delH1 (Rep_regT2 (invLift0 u h g h1 t2))))

lemma invLift_addH:

  (!!x y t. headers (g x t) = headers (g y t))
  ==> invLift u h g h1 (addH h2 t2) = addH2 h2 (g h1 t2)

lemma headers_invLift0_invariant:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t) |]
  ==> headers (Rep_regT2 (invLift0 u h g x t)) =
      headers (Rep_regT2 (invLift0 u h g y t))

lemma headers_invLift_invariant:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t) |]
  ==> headers (invLift u h g x t) = headers (invLift u h g y t)

lemma invLift_hConc:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t);
     regSkelOuter2 (invLift u h g h1 t1) = Some (hs1a, hs2a);
     regSkelOuter2 (invLift u h g h1 t2) = Some (hs1b, hs2b) |]
  ==> invLift u h g h1 (hConc t1 t2) =
      hConc
       (vConc (invLift u h g h1 t1)
         (tMap (const (h u (delH1 (invLift u h g h1 t2)))) (invLift u h g h1 t1)))
       (vConc
         (tMap (const (h u (delH1 (invLift u h g h1 t1)))) (invLift u h g h1 t2))
         (invLift u h g h1 t2))

lemma regSkelOuter2_invLift_EX:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t) |]
  ==> EX hs1. regSkelOuter2 (invLift u h g h1 t) = Some (hs1, headers t)

lemma delH1_invLift:

  [| !!t. headers (h u t) = headers t; !!t. h u (h u t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t) |]
  ==> delH1 (invLift u h g v t) =
      tFold (%h0 t0. addH h0 (delH1 (g v t0))) (hConcU (h u)) t

lemma h_u_delH1_invLift:

  [| !!t. headers (h u t) = headers t; !!t x. h u (h x t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t);
     !!h0 t0. h u (addH h0 (delH1 (g v t0))) = addH h0 (delH1 (g u t0)) |]
  ==> h u (delH1 (invLift u h g v t)) =
      tFold (%h0 t0. addH h0 (delH1 (g u t0))) hConc t

lemma headers_h_u_delH1_invLift:

  [| !!t. headers (h u t) = headers t; !!t x. h u (h x t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t);
     !!h0 t0. h u (addH h0 (delH1 (g v t0))) = addH h0 (delH1 (g u t0)) |]
  ==> headers (h u (delH1 (invLift u h g v t))) = headers t

lemma headers_delH1_invLift:

  [| !!t. headers (h u t) = headers t; !!t x. h u (h x t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t);
     !!h0 t0. h u (addH h0 (delH1 (g v t0))) = addH h0 (delH1 (g u t0)) |]
  ==> headers (delH1 (invLift u h g v t)) = headers t

lemma regSkelOuter2_dConcFill:

  [| !!t. headers (h u t) = headers t; !!t x. h u (h x t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t);
     regSkelOuter2 (invLift u h g h1 t1) = Some (hs1a, hs2a);
     regSkelOuter2 (invLift u h g h1 t2) = Some (hs1b, hs2b) |]
  ==> regSkelOuter2
       (tMap (const (h u (delH1 (invLift u h g h1 t2)))) (invLift u h g h1 t1)) =
      Some (hs1a, hs2b)

lemma headers_invLift_hConc:

  [| !!t. headers (h u t) = headers t; !!t x. h u (h x t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t);
     regSkelOuter2 (invLift u h g h1 t1) = Some (hs1a, hs2a);
     regSkelOuter2 (invLift u h g h1 t2) = Some (hs1b, hs2b) |]
  ==> headers (invLift u h g h1 (hConc t1 t2)) =
      append (headers (invLift u h g h1 t1)) (headers (invLift u h g h1 t2))

lemma headers_invLift:

  [| !!t. headers (h u t) = headers t; !!t x. h u (h x t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t) |]
  ==> headers (invLift u h g h1 t) = tFold (%h2 t2. headers (g h1 t2)) append t

lemma regSkelOuter2_invLift:

  [| !!t. headers (h u t) = headers t; !!t x. h u (h x t) = h u t;
     !!t1 t2. h u (hConc t1 t2) = hConc (h u t1) (h u t2);
     !!x y t. headers (g x t) = headers (g y t);
     !!h0 t0. h u (addH h0 (delH1 (g h1 t0))) = addH h0 (delH1 (g u t0)) |]
  ==> regSkelOuter2 (invLift u h g h1 t) =
      Some (tFold (%h2 t2. headers (g h1 t2)) append t, headers t)

The Inversion Operator for Two Dimensions

lemma delH1_invOp2:

  delH1 (invOp2 u v t) = tFold (%h t. addH h (slimH1 v t)) (hConcSH2 u) t

lemma headers_invOp2:

  headers (invOp2 u v t) = tFold (%h. headers) append t

lemma cs_invOp2:

  slimH2 u (delH1 (invOp2 u v t)) = tFold (%h t. addH h (slimH1 u t)) hConc t

lemma regSkelOuter2_invOp2:

  regSkelOuter2 (invOp2 u h1 t) = Some (tFold (%h. headers) append t, headers t)

lemma invOp2_hConc:

  [| regSkelOuter2 (invOp2 u h1 t1) = Some (hs1a, hs2a);
     regSkelOuter2 (invOp2 u h1 t2) = Some (hs1b, hs2b) |]
  ==> invOp2 u h1 (hConc t1 t2) =
      hConc (vConc (invOp2 u h1 t1) (spread1 hs1a (slimH2 u t2)))
       (vConc (spread1 hs1b (slimH2 u t1)) (invOp2 u h1 t2))

Two-Dimensional Inversion

lemma inverse2_addH:

  inverse2 u (addH h t) = invLift u slimH2 addH2 h t

lemma inverse2_hConc:

  inverse2 u (hConc t1 t2) = hConc (inverse2 u t1) (inverse2 u t2)

lemma tFold_tFold_tFold_inverse2:

  [| assoc c2; assoc c3; assoc c1; assoc c5; assoc c6;
     !!h ha hb t. a4 hb (a5 ha (a6 h t)) = a1 h (a2 ha (a3 hb t));
     !!h ha t1 t2.
        c1 (a1 h (a2 ha t1)) (a1 h (a2 ha t2)) = a1 h (a2 ha (c3 t1 t2));
     !!x y z. a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
     !!x1 x2 y1 y2. c1 (c5 x1 y1) (c5 x2 y2) = c5 (c1 x1 x2) (c1 y1 y2);
     !!x. LRunit c1 (a1 u x); !!x y. LRunit c5 (a5 y (a6 u x));
     !!x y z. LRunit c1 (a1 z (a5 y (a6 u x)));
     !!h x1 x2. c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2) |]
  ==> tFold a4 c1 (tMap (tFold a5 c5 o tMap (tFold a6 c6)) (inverse2 u t)) =
      tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFold a3 c3)) t)

lemma tFold_tFold_tFold0_inverse2:

  [| assoc c2; assoc c3; assoc c1; assoc c5; assoc c6;
     !!h ha hb t. a4 hb (a5 ha h) = a1 h (a2 ha hb);
     !!h ha t1 t2.
        c1 (a1 h (a2 ha t1)) (a1 h (a2 ha t2)) = a1 h (a2 ha (c3 t1 t2));
     !!x y z. a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
     !!x1 x2 y1 y2. c1 (c5 x1 y1) (c5 x2 y2) = c5 (c1 x1 x2) (c1 y1 y2);
     !!x. LRunit c1 (a1 u x); !!x y. LRunit c5 (a5 y u);
     !!x y z. LRunit c1 (a1 z (a5 y u));
     !!h x1 x2. c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2) |]
  ==> tFold a4 c1 (tMap (tFold a5 c5 o tMap (tFold0 c6)) (inverse2 u t)) =
      tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFold0 c3)) t)

lemma tFold_tFold_tFoldC_inverse2:

  [| assoc c1; assoc c2; assoc c3; assoc c5; assoc c6;
     !!h ha hb t. a4 hb (a5 ha (a6 h)) = a1 h (a2 ha (a3 hb));
     !!h ha t1 t2.
        c1 (a1 h (a2 ha t1)) (a1 h (a2 ha t2)) = a1 h (a2 ha (c3 t1 t2));
     !!x y z. a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
     !!x1 x2 y1 y2. c1 (c5 x1 y1) (c5 x2 y2) = c5 (c1 x1 x2) (c1 y1 y2);
     !!x. LRunit c1 (a1 u x); !!x y. LRunit c5 (a5 y (a6 u));
     !!x y z. LRunit c1 (a1 z (a5 y (a6 u)));
     !!h x1 x2. c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2) |]
  ==> tFold a4 c1 (tMap (tFold a5 c5 o tMap (tFoldC a6 c6)) (inverse2 u t)) =
      tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFoldC a3 c3)) t)

lemma tFold_tFold_tFold_inverse2_wrapped:

  [| assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6;
     !!h ha hb t. w2 (a4 hb (a5 ha (a6 h t))) = w1 (a1 h (a2 ha (a3 hb t)));
     !!x y. w2 (c4 x y) = c7 (w2 x) (w2 y); !!x y. c7 (w1 x) (w1 y) = w1 (c1 x y);
     !!x y. w2 (c5 x y) = c8 (w2 x) (w2 y);
     !!h x y. c7 (w1 (a1 h x)) (w1 (a1 h y)) = w1 (a1 h (c2 x y));
     !!h ha x y.
        c7 (w1 (a1 h (a2 ha x))) (w1 (a1 h (a2 ha y))) =
        w1 (a1 h (a2 ha (c3 x y)));
     !!x y z. a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
     !!x1 x2 y1 y2. c4 (c5 x1 y1) (c5 x2 y2) = c5 (c4 x1 x2) (c4 y1 y2);
     !!x. LRunit c8 (w1 (a1 u x)); !!x y. LRunit c5 (a5 y (a6 u x));
     !!x y z. LRunit c4 (a4 z (a5 y (a6 u x)));
     !!h x1 x2. c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2) |]
  ==> w2 (tFold a4 c4 (tMap (tFold a5 c5 o tMap (tFold a6 c6)) (inverse2 u t))) =
      w1 (tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFold a3 c3)) t))

lemma tFold_tFold_tFoldC_inverse2_wrapped:

  [| assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6;
     !!h ha hb t. w2 (a4 hb (a5 ha (a6 h))) = w1 (a1 h (a2 ha (a3 hb)));
     !!x y. w2 (c4 x y) = c7 (w2 x) (w2 y); !!x y. c7 (w1 x) (w1 y) = w1 (c1 x y);
     !!x y. w2 (c5 x y) = c8 (w2 x) (w2 y);
     !!h x y. c7 (w1 (a1 h x)) (w1 (a1 h y)) = w1 (a1 h (c2 x y));
     !!h ha x y.
        c7 (w1 (a1 h (a2 ha x))) (w1 (a1 h (a2 ha y))) =
        w1 (a1 h (a2 ha (c3 x y)));
     !!x y z. a4 x (c5 y z) = c5 (a4 x y) (a4 x z);
     !!x1 x2 y1 y2. c4 (c5 x1 y1) (c5 x2 y2) = c5 (c4 x1 x2) (c4 y1 y2);
     !!x. LRunit c8 (w1 (a1 u x)); !!x y. LRunit c5 (a5 y (a6 u));
     !!x y z. LRunit c4 (a4 z (a5 y (a6 u)));
     !!h x1 x2. c5 (a1 h x1) (a1 h x2) = a1 h (c2 x1 x2) |]
  ==> w2 (tFold a4 c4 (tMap (tFold a5 c5 o tMap (tFoldC a6 c6)) (inverse2 u t))) =
      w1 (tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFoldC a3 c3)) t))

lemma wrapped_tFold:

  [| assoc c4; assoc c7; !!x y. w2 (c4 x y) = c7 (w2 x) (w2 y) |]
  ==> w2 (tFold a4 c4 t) = tFold (%h t. w2 (a4 h t)) c7 t

lemma wrapped_foldr1:

  [| assoc c5; assoc c8; !!x y. f (c5 x y) = c8 (f x) (f y) |]
  ==> f (foldr1 c5 xs) = foldr1 c8 (map1 f xs)

lemma wrapped2_tFold:

  [| assoc c5; assoc c7;
     !!h x y. w2 (a4 h (c5 x y)) = c7 (w2 (a4 h x)) (w2 (a4 h y)) |]
  ==> (%x. w2 (a4 x (tFold a8 c5 t))) =
      (%x. tFold (%h t. w2 (a4 x (a8 h t))) c7 t)

lemma tFold_tFold_tFold_inverse2_gen:

  [| assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6; assoc c7;
     !!h ha hb t. w2 (a4 hb (a5 ha (a6 h t))) = w1 (a1 h (a2 ha (a3 hb t)));
     !!x y. c7 (w1 x) (w1 y) = w1 (c1 x y);
     !!h ha x y.
        w1 (c1 (a1 h (a2 ha x)) (a1 h (a2 ha y))) = w1 (a1 h (a2 ha (c3 x y)));
     !!h x y. w2 (a4 h (c5 x y)) = w2 (c4 (a4 h x) (a4 h y));
     !!x y. w2 (c4 x y) = c7 (w2 x) (w2 y);
     !!x1 x2 y1 y2.
        c7 (w2 (c4 x1 x2)) (w2 (c4 y1 y2)) = w2 (c4 (c4 x1 y1) (c4 x2 y2));
     !!x. LRunit c7 (w1 (a1 u x));
     !!h x y. w1 (c1 (a1 h x) (a1 h y)) = w1 (a1 h (c2 x y)) |]
  ==> w2 (tFold a4 c4 (tMap (tFold a5 c5 o tMap (tFold a6 c6)) (inverse2 u t))) =
      w1 (tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFold a3 c3)) t))

lemma tFold_tFold_tFoldC_inverse2_gen:

  [| assoc c1; assoc c2; assoc c3; assoc c4; assoc c5; assoc c6; assoc c7;
     !!h ha hb. w2 (a4 hb (a5 ha (a6 h))) = w1 (a1 h (a2 ha (a3 hb)));
     !!x y. c7 (w1 x) (w1 y) = w1 (c1 x y);
     !!h ha x y.
        w1 (c1 (a1 h (a2 ha x)) (a1 h (a2 ha y))) = w1 (a1 h (a2 ha (c3 x y)));
     !!h x y. w2 (a4 h (c5 x y)) = w2 (c4 (a4 h x) (a4 h y));
     !!x y. w2 (c4 x y) = c7 (w2 x) (w2 y);
     !!x1 x2 y1 y2.
        c7 (w2 (c4 x1 x2)) (w2 (c4 y1 y2)) = w2 (c4 (c4 x1 y1) (c4 x2 y2));
     !!x. LRunit c7 (w1 (a1 u x));
     !!h x y. w1 (c1 (a1 h x) (a1 h y)) = w1 (a1 h (c2 x y)) |]
  ==> w2 (tFold a4 c4 (tMap (tFold a5 c5 o tMap (tFoldC a6 c6)) (inverse2 u t))) =
      w1 (tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFoldC a3 c3)) t))

lemma id_tFold_tFold_tFoldC_inverse2_gen:

  [| assoc c1; assoc c2; assoc c3; assoc c5; assoc c6;
     !!h ha hb. a4 hb (a5 ha (a6 h)) = a1 h (a2 ha (a3 hb));
     !!h ha x y. c1 (a1 h (a2 ha x)) (a1 h (a2 ha y)) = a1 h (a2 ha (c3 x y));
     !!h x y. a4 h (c5 x y) = c1 (a4 h x) (a4 h y);
     !!x1 x2 y1 y2. c1 (c1 x1 x2) (c1 y1 y2) = c1 (c1 x1 y1) (c1 x2 y2);
     !!x. LRunit c1 (a1 u x); !!h x y. c1 (a1 h x) (a1 h y) = a1 h (c2 x y) |]
  ==> id (tFold a4 c1 (tMap (tFold a5 c5 o tMap (tFoldC a6 c6)) (inverse2 u t))) =
      id (tFold a1 c1 (tMap (tFold a2 c2 o tMap (tFoldC a3 c3)) t))