Theory NU_PreEqu

(*<*)
theory NU_PreEqu
imports NU_Fresh
begin
(*>*)

section ‹Pre-Equality›

text ‹
  Defines the relation which captures the notion of alpha-equivalence (on open terms) 
  and proves this relation is an equivalence relation.
›

inductive equ :: "fresh_envs  trm  trm  bool" (" _  _  _" [80,80,80] 80) where
equ_abst_ab[intro!]: "ab;(nabla  a  t2);(nabla  t1  (swap [(a,b)] t2)) 
                       (nabla  Abst a t1  Abst b t2)" |
equ_abst_aa[intro!]: "(nabla  t1  t2)  (nabla  Abst a t1  Abst a t2)" |
equ_unit[intro!]:    "(nabla  Unit  Unit)" |
equ_atom[intro!]:    "a=bnabla  Atom a  Atom b" |
equ_susp[intro!]:    "( c  ds pi1 pi2. (c,X)  nabla)  (nabla  Susp pi1 X  Susp pi2 X)" |
equ_paar[intro!]:    "(nabla  t1t2);(nabla  s1s2)  (nabla  Paar t1 s1  Paar t2 s2)" |
equ_func[intro!]:    "(nabla  t1  t2)  (nabla  Func F t1  Func F t2)"

inductive_cases Equ_elims:
"nabla  Atom a  Atom b"
"nabla  Unit  Unit"
"nabla  Susp pi1 X  Susp pi2 X"
"nabla  Paar s1 t1  Paar s2 t2"
"nabla  Func F t1  Func F t2"
"nabla  Abst a t1  Abst a t2"
"nabla  Abst a t1  Abst b t2"

lemma equ_depth: 
  assumes "nabla  t1  t2"
  shows "depth t1 = depth t2"
  using assms by (rule equ.induct, simp_all)

lemma rev_pi_pi_equ: 
  shows "(nabla  swap (rev pi) (swap pi t)  t)"
proof(induct t)
  case (Susp pi' X)
  then show ?case 
    using ds_cancel_pi_left[of _ rev pi @ pi _ []]
    ds_rev_pi_pi elem_ds ds_rev_pi_id by auto
qed (auto)
  
lemma equ_pi_right: 
  assumes "a  ds [] pi. nabla  a  t"
  shows "nabla  t  swap pi t"
  using assms
proof(induct t arbitrary: pi)
   case (Abst b t')
   have "swapas pi b = b  swapas pi b  b" by simp
  moreover 
  { assume eq: "swapas pi b = b"
    have "nabla  Abst b t'  Abst b (swap pi t')"
      by (metis Abst.hyps Abst.prems Fresh_elims(1) elem_ds eq equ_abst_aa)
    then have "nabla  Abst b t'  swap pi (Abst b t')" using eq by simp
  }
  moreover
  { assume neq: "b  swapas pi b"  
    obtain c where c_def: "c = swapas pi b" by simp
    have "c  ds [] pi"
      by (metis append.right_neutral c_def ds_cancel_pi_front ds_cancel_pi_left ds_elem neq)
    then have one: "nabla  c  Abst b t'" using assms Abst.prems by auto
    have two: "b  c" using neq c_def by blast
    have "nabla  c  t'" using one two by cases auto
    have "nabla  Abst b t'  Abst c (swap pi t')" 
    proof(rule equ_abst_ab)
      show "b  c" using neq c_def by blast
      have b_is_swap: "b = swapas (rev pi) c" using c_def by simp
      show "nabla  b  swap pi t'" 
        using Abst.prems Fresh_elims(1) ds_elem fresh_swap_right neq swapas_rev_pi_a by metis
      show "nabla  t'  swap [(b, c)] (swap pi t')"
      proof -
         have fresh_ext:
          "a  ds [] ((b,c) # pi). nabla  a  t'"
        proof (rule ballI)
          fix a assume A: "a  ds [] ((b,c)#pi)"
          then have "a = c  a  ds [] pi"
            using c_def ds_7 neq by auto  
          then show "nabla  a  t'"
          proof
            assume "a = c"
            with nabla  c  t' show ?thesis by simp
          next
            assume "a  ds [] pi"
            show ?thesis 
            proof(rule Fresh_elims(1)[of nabla a b t'], goal_cases)
              case 1
              then show ?case
                using Abst.prems a  ds [] pi
              by simp
            next
              case 2
              then show ?case by simp
            next
              case 3
              have "a  swapas ((b, c) # pi) a" 
                using A elem_ds
                by blast
              hence "a  b" using c_def A 
                by (auto simp add: if_split)
              hence False using 3 by simp
              then show ?case by simp
          qed
        qed
      qed
        from Abst.hyps[OF fresh_ext]
        have "nabla  t'  swap ([(b,c)]@pi) t'"
          by simp
        moreover have "swap ([(b,c)]@pi) t' = swap [(b,c)] (swap pi t')"
          using swap_append by blast
        ultimately show ?thesis by simp
      qed
    qed
   then have "nabla  Abst b t'  swap pi (Abst b t')" using neq c_def by force
 }
  ultimately show ?case by argo
next
  case (Susp pi' X)
  have "ads [] pi. nabla  a  Susp pi' X" by fact
  then have "nabla  Susp pi' X  Susp (pi @ pi') X"
   using Fresh_elims(4) equ_susp ds_def ds_cancel_pi_left
   by (metis (lifting) append_self_conv2 swapas_rev_pi_a)
  then show ?case by simp
next
  case Unit
  then show ?case 
    using equ_unit swap.simps(2) by force
next
  case (Atom b)
    then show ?case
      apply simp
    apply (rule equ_atom)
    using Fresh_elims(3) ds_elem_cp
    by metis
next
  case (Paar t1 t2)
  then have hypsp1: "(ads [] pi.  nabla  a  t1)"
    and hypsp2: "(ads [] pi.  nabla  a  t2)"
    using Paar.prems Fresh_elims(5) by meson+
  have "nabla  Paar t1 t2  Paar (swap pi t1) (swap pi t2)"
    using Paar.hyps(1,2) hypsp1 hypsp2 by blast
  then show ?case by simp
next
  case (Func f t')
  then have hypsf: "ads [] pi. nabla  a  t'" using fresh_func
    by (metis Fresh_elims(6))
  have "nabla  Func f t'  Func f (swap pi t')"
    using Func.hyps hypsf by blast
  then show ?case
    by simp
qed

lemma pi_comm: 
  shows "nabla  (swap (pi @ [(a,b)]) t)  (swap ([(swapas pi a, swapas pi b)] @ pi) t)"
proof(induct t)
  case (Abst c t)
  then show ?case using swapas_comm by force
next
  case (Susp π' X)
  have rew1:
    "swap (pi @ [(a,b)]) (Susp π' X) = Susp (pi @ [(a,b)] @ π') X"
    by simp
  have rew2:
    "swap ([(swapas pi a, swapas pi b)] @ pi) (Susp π' X) 
    = Susp ([(swapas pi a, swapas pi b)] @ pi @ π') X"
    by simp
  have fresh:
  "c  ds (pi @ [(a,b)] @ π') ([(swapas pi a, swapas pi b)] @ pi @ π'). (c, X)  nabla"
    using swapas_append swapas_comm ds_def by simp
  from rew1 rew2 fresh
  show ?case
    using equ_susp by simp
next
  case Unit
  then show ?case by force
next
  case (Atom c)
  then show ?case 
    using equ_atom swapas_comm by auto
next
  case (Paar t1 t2)
  then show ?case by force
next
  case (Func f t)
  then show ?case by force
qed

lemma l3_jud: 
  assumes "(nabla  t1  t2)"
  shows "(nabla  a  t1)  (nabla  a  t2)"
  using assms
proof(induction rule: equ.induct)
  case (equ_abst_ab b c nabla t2 t1)
  then show ?case 
    using fresh_swap_left Fresh_elims(1) fresh_abst_aa fresh_abst_ab rev_singleton_conv swapa.simps swapas.simps(1,2)
    by metis
next
  case (equ_abst_aa nabla t1 t2 b)
  then show ?case 
    using fresh_swap_left Fresh_elims(1) fresh_abst_aa fresh_abst_ab 
    by metis
next
  case (equ_unit nabla)
  then show ?case
    by blast
next
  case (equ_atom b c nabla)
  then show ?case 
    by simp
next
  case (equ_susp pi1 pi2 X nabla)
  then show ?case 
    using Fresh_elims(4) ds_elem_cp ds_rev fresh_susp swapas_append swapas_rev_pi_a
    by metis
next
  case (equ_paar nabla t1 t2 s1 s2)
  then show ?case
    using Fresh_elims(5) by blast
next
  case (equ_func nabla t1 t2 f)
  then show ?case 
    using Fresh_elims(6) by blast
qed

lemma ds_empty_equiv_1:
  assumes "ds pi1 pi2 = {}"
  shows "nabla  swap pi1 t1  t2  nabla  swap pi2 t1  t2"
  using assms
proof(induction t1 arbitrary: t2)
  case (Abst a t1')
  then obtain b t2'
    where t2: "t2 = Abst b t2'"
    by(auto elim: equ.cases)
  with Abst have i: "nabla  Abst (swapas pi1 a) (swap pi1 t1')  Abst b t2'"
    using swap.simps(4) by simp
  then show ?case
  proof(cases swapas pi1 a = b)
    case True
    then have "nabla  swap pi1 t1'  t2'" 
      using Abst i Equ_elims(6) by blast
    then have ii: "nabla  swap pi2 t1'  t2'"
      using Abst by simp
    then have "nabla  Abst (swapas pi2 a) (swap pi2 t1')  Abst b t2'"
      using True ds_swapas_eq[OF Abst(3), of a] equ_abst_aa[OF ii, of swapas pi2 a] 
      by simp
    then show ?thesis 
      using t2 by simp
  next
    case False
    then have equ_ab_pi1: "nabla  swap pi1 t1'  swap [(swapas pi1 a, b)] t2'" 
      and fresh_ab_pi1: "nabla  swapas pi1 a  t2'"
      using i Equ_elims(7)[of nabla swapas pi1 a swap pi1 t1' b t2'] 
      by blast+
    have equ_ab_pi2: "nabla  swap pi2 t1'  swap [(swapas pi2 a, b)] t2'"
      using equ_ab_pi1 ds_swapas_eq[OF Abst(3), of a] 
        Abst(3) Abst(1)[of swap [(swapas pi1 a, b)] t2'] by auto
    have fresh_ab_pi2: "nabla  swapas pi2 a  t2'"
      using fresh_ab_pi1 ds_swapas_eq[OF Abst(3), of a] by simp
    with equ_ab_pi2 have "nabla  Abst (swapas pi2 a) (swap pi2 t1')  Abst b t2'"
      using equ_abst_ab[OF False, of nabla t2'] ds_swapas_eq[OF Abst(3), of a] by simp
    then show ?thesis using t2 by simp
  qed
next
  case (Susp pi X)
  then obtain pi'
    where t2: "t2 = Susp pi' X"
    by (auto elim:equ.cases)
  with Susp have i: "nabla  Susp (pi1 @ pi) X  Susp pi' X" 
    by simp
  then have " c  ds (pi1@pi) pi'. (c,X)  nabla"
    using Equ_elims(3)[OF i] by auto
  with Susp have " c  ds (pi2@pi) pi'. (c,X)  nabla"
    using ds_cancel_pi_left ds_sym ds_trans
    by blast
  then have "nabla  Susp (pi2 @ pi) X  Susp pi' X"
    using equ_susp by simp
  then show ?case using t2 swap.simps(3) by simp
next
  case (Atom a)
  then show ?case
    using ds_swapas_eq[OF Atom(2), of a]
    by (auto elim: equ.cases)
qed (auto elim: equ.cases)

lemma ds_empty_equiv_2:
  assumes "ds pi1 pi2 = {}"
  shows "nabla  t1  swap pi1 t2  nabla  t1  swap pi2 t2"
using assms
proof(induction t2 arbitrary: pi1 pi2 t1)
  case (Abst b t2')
  then obtain a t1'
    where t1: "t1 = Abst a t1'"
    by(auto elim: equ.cases)
  with Abst have i: "nabla  Abst a t1'  Abst (swapas pi1 b) (swap pi1 t2')"
    using swap.simps(4) by simp
  then show ?case
  proof(cases swapas pi1 b = a)
    case True
    then have "nabla  t1'  swap pi1 t2'" 
      using Abst i Equ_elims(6) by blast
    then have ii: "nabla  t1'  swap pi2 t2'"
      using Abst by simp
    then have "nabla  Abst a t1'  Abst (swapas pi2 b) (swap pi2 t2')"
      using True ds_swapas_eq[OF Abst(3), of b] equ_abst_aa[OF ii, of swapas pi2 b] 
      by simp
    then show ?thesis 
      using t1 by simp
  next
    case False
    then have equ_ab: "nabla  t1'  swap [(a, swapas pi1 b)] (swap pi1 t2')" 
      and fresh_ab_pi1: "nabla  a  swap pi1 t2'"
      using i Equ_elims(7) by blast+

    then have equ_ab_pi1: "nabla  t1'  swap ([(a, swapas pi1 b)]@ pi1) t2'"
      using swap_append[of [(a, swapas pi1 b)] pi1 t2'] by simp

    have ds_empty: "ds ([(a, swapas pi1 b)] @ pi1) ([(a, swapas pi2 b)] @ pi2) = {}"
      using Abst(3) ds_swapas_eq[OF Abst(3), of b] 
        ds_cancel_pi_front[of [(a, swapas pi1 b)] pi1 pi2] by simp
    
    hence "nabla  t1'  swap ([(a, swapas pi2 b)]@ pi2) t2'"
      using Abst(1)[OF equ_ab_pi1 ds_empty] by simp
    hence equ_ab_pi2: "nabla  t1'  swap [(a, swapas pi2 b)] (swap pi2 t2')"
      using swap_append[of [(a, swapas pi2 b)] pi2 t2'] by simp

    have fresh_ab_pi2: "nabla  a  swap pi2 t2'"
      using ds_empty_fresh_2 Abst(3) fresh_ab_pi1 by auto
    with equ_ab_pi2 have "nabla  Abst a t1'  Abst (swapas pi2 b) (swap pi2 t2')"
      using equ_abst_ab ds_swapas_eq False assms Abst(3) by auto
    then show ?thesis using t1 by simp
  qed
next
  case (Susp pi' X)
  then obtain pi
    where t1: "t1 = Susp pi X"
    by (auto elim:equ.cases)
  with Susp have i: "nabla  Susp pi X  Susp (pi1 @ pi') X" 
    by simp
  then have " c  ds pi (pi1 @ pi'). (c,X)  nabla"
    using Equ_elims(3)[OF i] by auto
  with Susp have " c  ds pi (pi2 @ pi'). (c,X)  nabla"
    using ds_cancel_pi_left ds_sym ds_trans
    by blast
  then have "nabla  Susp pi X  Susp (pi2 @ pi') X"
    using equ_susp by simp
  then show ?case using t1 swap.simps(3) by simp
next
  case (Atom a)
  then show ?case
    using ds_swapas_eq by (auto elim: equ.cases)
qed (auto elim: equ.cases)

lemma equ_equivariance:
  assumes "nabla  t1  t2"
  shows "nabla  swap pi t1  swap pi t2"
  using assms
proof(induct rule: equ.induct)
  case (equ_abst_ab a b nabla t2' t1')
  have i: "nabla  swapas pi a  swap pi t2'"
    using fresh_swap_eqvt[OF equ_abst_ab(2), of pi] by simp

  have "nabla  swap pi t1'  swap (pi @ [(a,b)]) t2'"
    using equ_abst_ab(4) swap_append[of pi [(a,b)] t2'] by simp
  then have "nabla  swap pi t1'  swap ([(swapas pi a, swapas pi b)] @ pi) t2'"
    using ds_empty_equiv_2[OF ds_comm[of pi a b]] by auto
  then have ii: "nabla  swap pi t1'  swap [(swapas pi a, swapas pi b)] (swap pi t2')"
    using ds_empty_equiv_2[OF ds_comm[of pi a b]] 
      swap_append[of [(swapas pi a, swapas pi b)] pi t2'] by simp

  have iii: "swapas pi a  swapas pi b" 
    using equ_abst_ab.hyps(1) swapas_rev_pi_a by blast
  
  with i ii
  have "nabla  Abst (swapas pi a) (swap pi t1')  Abst (swapas pi b) (swap pi t2')"
    using equ.equ_abst_ab by auto
  hence "nabla  swap pi (Abst a t1')  swap pi (Abst b t2')"
    using swap.simps(4) by simp
  then show ?case by simp
next
  case (equ_abst_aa nabla t1' t2' a)
  then show ?case
    using equ.equ_abst_aa by simp
next
  case (equ_susp pi1 pi2 X nabla)
  then show ?case using ds_cancel_pi_front
    by auto
qed (auto)

lemma swap_inv_side: 
  shows "nabla  swap pi t1  t2 = nabla  t1  swap (rev pi) t2"
proof
  
  {assume assm1: "nabla  swap pi t1  t2"
  from equ_equivariance[OF assm1, of rev pi]
  have "nabla  swap (rev pi @ pi) t1   swap (rev pi) t2"
    using swap_append[of rev pi pi t1] by simp
  then show "nabla  t1  swap (rev pi) t2"
    using ds_empty_equiv_1[OF ds_rev_pi_id[of pi], of nabla t1 swap (rev pi) t2] 
      swap_id[of t1] by simp}

  {assume assm2: "nabla  t1  swap (rev pi) t2"
  from equ_equivariance[OF assm2, of pi]
  have "nabla  swap pi t1  swap (pi @ rev pi) t2"
    using swap_append[of pi rev pi t2] by simp
  then show "nabla  swap pi t1  t2"
    using ds_empty_equiv_2[OF ds_pi_rev_id[of pi], of nabla swap pi t1 t2] 
      swap_id[of t2] by simp}
qed

lemma equ_swap_abba:
  assumes "n = depth t1"
  shows "nabla  swap [(a,b)] t1  t2  nabla  t1  swap [(b,a)] t2"
proof-
  assume "nabla  swap [(a,b)] t1  t2"
  with ds_baab[of b a] 
  have "nabla  swap [(b,a)] t1  t2"
    using ds_empty_equiv_1 by blast
    then show ?thesis
    using swap_inv_side[of nabla [(b,a)]] by simp
qed

lemma equ_equiv_pi: 
  assumes "a  ds pi1 pi2. nabla  a  t"
  shows "nabla  swap pi1 t  swap pi2 t"
  using assms equ_pi_right[of rev pi1 @ pi2 nabla t]
    swap_inv_side[of nabla pi1 t swap pi2 t] ds_rev swap_append by simp

lemma equ_symm:
  shows "(nabla  t1  t2)  (nabla  t2  t1)"
proof(induction rule: equ.induct)
  case (equ_abst_ab a b nabla t2' t1')
  have i: "nabla  b  swap [(a, b)] t2'" 
    using fresh_swap_eqvt[of nabla a t2' "[(a,b)]"] equ_abst_ab(2) by auto
  with equ_abst_ab(4) 
  have b_fresh: "nabla  b  t1'"
    using l3_jud by blast
  from equ_abst_ab(4) 
  have ii: "nabla  t2'  swap [(b, a)] t1'"
    using equ_swap_abba by simp
  show ?case 
    using equ.equ_abst_ab[OF equ_abst_ab(1)[symmetric] b_fresh ii] by simp
next
  case (equ_abst_aa nabla t1' t2' a)
  then show ?case 
    using equ.equ_abst_aa[OF equ_abst_aa(2), of a] by simp
next
  case (equ_unit nabla)
  then show ?case by auto
next
  case (equ_atom a b nabla)
  then show ?case by auto
next
  case (equ_susp pi1 pi2 X nabla)
  then show ?case 
    using ds_sym by auto
next
  case (equ_paar nabla t1' t2' s1' s2')
  then show ?case by auto
next
  case (equ_func nabla t1' t2' f)
  then show ?case 
    using equ.equ_func[OF equ_func(2), of f] by simp
qed

lemma equ_trans:
  assumes "nabla  t1  t2" "nabla  t2  t3"
  shows "nabla  t1  t3"
  using assms
proof(induction depth t1 arbitrary: t1 t2 t3 rule: nat_less_induct)
  case 1
  note IH = this
  have IH_usable: 
    "depth t1' < depth t1  nabla  t1'  t2'   nabla  t2'  t3'  nabla  t1'  t3'"
    for t1' t2' t3' using IH by blast
  have "nabla  t1  t2  nabla  t2  t3   nabla  t1  t3"
  proof-
    assume t12: "nabla  t1  t2" and t23: "nabla  t2  t3"
    show ?thesis
     proof(cases rule: equ.cases[OF nabla  t1  t2])
       case (1 a b nabla t2' t1')
       from 1(2) have deptht1: "depth t1' < depth t1"
         using depth.simps(4) by auto
       from t23 show ?thesis
       proof(cases rule: equ.cases)
         case (equ_abst_ab b c t3' t2')
         then show ?thesis 
         proof(cases "a = c")
           case True
           have i: "nabla  swap [(c,b)] t2'  swap ([(c,b)]@[(b,c)]) t3'"
             using equ_equivariance[OF equ_abst_ab(5), of [(c,b)]] 1(1)
               swap_append[of [(c,b)] [(b,c)] t3'] by simp
           have ii: "nabla  swap [(c,b)] t2'  t3'"
             using ds_empty_equiv_2[OF ds_baab_id[OF equ_abst_ab(3)] i] by simp
           with equ_abst_ab 1 True
           have iii: "nabla  t1'  swap [(c, b)] t2'" by blast
           with ii have "nabla  t1'  t3'"
             using IH_usable[OF deptht1, of swap [(c, b)] t2' t3'] 1(1)
             by simp
           then show ?thesis using True equ_abst_ab(2) 1(1,2) by auto
         next
           case False

           have deptht2: "depth (swap [(a,b)] t2') < depth t1"
              using depth.simps(4) equ_depth[OF 1(6)] swap_depth 1(3) deptht1
              equ_abst_ab(1) by simp

            from equ_abst_ab(1,4,5) 1(1,3,5)
              have ii: "nabla  a  swap [(b,c)] t3'"
                using l3_jud by simp

            then have a_fresh_t3: "nabla  a  t3'"
              using fresh_swap_left[OF ii] False equ_abst_ab 1 by simp
            have b_fresh_t3: "nabla  b  t3'" 
              using equ_abst_ab(4) 1(1) by simp

            from 1(1) equ_abst_ab(5)
            have "nabla  swap [(a,b)] t2'  swap ([(a,b)]@[(b,c)]) t3'"
              using equ_equivariance[OF equ_abst_ab(5)]
             swap_append[of [(a, b)] [(b,c)] t3'] by simp
            then have iii: "nabla  swap [(a,b)] t2'  swap ([(a,b),(b,c)]) t3'"
              by simp
            
            have "ds [(a,b), (b,c)] [(a,c)] = {a,b}" 
              using ds_acabbc equ_abst_ab 1 False by simp
            with a_fresh_t3 b_fresh_t3 
            have iv: "nabla  swap [(a,b),(b,c)] t3'  swap [(a,c)] t3'"
              using equ_equiv_pi by simp

            with 1(1) iii have "nabla  swap [(a,b)] t2'  swap [(a,c)] t3'"
              using IH_usable[OF deptht2, of swap ([(a,b),(b,c)]) t3' swap [(a,c)] t3']
              by simp

            with 1(1,3,6) have "nabla  t1'  swap [(a,c)] t3'"
              using IH_usable[OF deptht1, of swap [(a, b)] t2' swap [(a,c)] t3']
              equ_abst_ab(1) by simp
            
            with 1(1,2) equ_abst_ab(2) 
            show ?thesis using equ.equ_abst_ab[OF False a_fresh_t3] by simp
         qed
       next
         case (equ_abst_aa t2' t3' b)
         from this(3) 1(1)
         have i: "nabla  swap [(a,b)] t2'  swap [(a,b)] t3'"
           using equ_equivariance[of nabla t2' t3' [(a,b)]] by simp

         have "nabla  b  swap [(a,b)] t2'" 
           using 1(1,3,4,5) equ_abst_aa(1) fresh_swap_eqvt[of nabla a t2' [(a,b)]]
           by auto
         then have ii: "nabla  b  swap [(a,b)] t3'"
           using l3_jud[OF i, of b] by simp
         have "nabla  swapas [(a,b)] b  t3'"
           using fresh_swap_left[OF ii] by simp
         then have a_fresh_t3: "nabla  a  t3'"
           using 1(3,4) equ_abst_aa(1) by simp

         have is_equ: "nabla  t1'  swap [(a,b)] t3'"
           using 1 i IH_usable[OF deptht1, of swap [(a,b)] t2' swap [(a,b)] t3']
           equ_abst_aa(1) by auto
          
         from a_fresh_t3 is_equ show ?thesis
           using 1 equ_abst_aa(1,2) equ.equ_abst_ab by simp
       qed (auto simp add: 1 t12)
     next
       case (2 nabla t1' t2' a)
       have deptht1: "depth t1' < depth t1"
         using depth.simps(4) 2(2) by simp
         from t23 show ?thesis 
         proof(cases rule: equ.cases)
           case (equ_abst_ab a c t3' t2')
           have "nabla  t1'  swap [(a,c)] t3'"
             using 2(1,2,3,4) IH_usable[OF deptht1, of t2' swap [(a,c)] t3'] 
            equ_abst_ab(1,4,5) by simp
           then show ?thesis
             using equ.equ_abst_ab[OF equ_abst_ab(3)]
               2(1,2,3) equ_abst_ab(1,2,4) by auto
         next
           case (equ_abst_aa t2' t3' a)
           then show ?thesis 
             using 1 2(1,2,3,4) by auto
         qed (auto simp add: 2)
     next
       case (3 nabla)
        from t23 show ?thesis
        proof(cases rule: equ.cases)
          case equ_unit
          then show ?thesis using t12 by auto
        qed (auto simp add: 3)
     next
       case (4 a b nabla)
        from t23 show ?thesis 
        proof(cases rule: equ.cases)
          case (equ_atom a b)
          then show ?thesis
            using t12 by auto
        qed (auto simp add: 4)
     next
       case (5 pi1 pi2 X nabla)
        from t23 show ?thesis 
        proof(cases rule: equ.cases)
          case (equ_susp pi1 pi2 X)
          then show ?thesis 
            using ds_trans 5 by blast
        qed (auto simp add: 5)
     next
       case (6 nabla t1' t2' s1' s2')
        from t23 show ?thesis 
        proof(cases rule: equ.cases)
          case (equ_paar t2' t3' s2' s3')
          have deptht1: "depth t1' < depth t1" 
            using 6(2) by simp
         have depths1: "depth s1' < depth t1" 
           using 6(2) by simp
         have a: "nabla  t1'  t2'" 
           using "6"(3,4) equ_paar by auto
         have b: "nabla  s1'  s2'" 
           using "6" equ_paar by auto
         from a have t1_equal_t3: "nabla  t1'  t3'" 
           using IH_usable[of t1' t2' t3'] equ_paar(3) 6(1) deptht1
           by simp
         from b have s1_equal_s3: "nabla  s1'  s3'" 
           using IH_usable[of s1' s2' s3'] equ_paar(4) 6(1) depths1
           by simp
         from t1_equal_t3 s1_equal_s3 show ?thesis 
           using equ.equ_paar[of nabla t1' t3' s1' s3'] 6(1,2) equ_paar(2)
           by simp
        qed (auto simp add: 6)
     next
       case (7 nabla t1 t2 F)
        from t23 show ?thesis 
       proof(cases rule: equ.cases)
         case (equ_func t1 t2 F)
         then show ?thesis 
           using 1 7(1,2,3,4) by auto
       qed (auto simp add: 7)
     qed
   qed
   then show ?case 
     using IH(2,3) by blast
 qed

lemma pi_right_equ_help:
  assumes "(n = depth t)"
  shows "nabla  t  swap pi t   a  ds [] pi. nabla  a  t"
  using assms 
proof(induction n arbitrary: t pi rule: nat_less_induct)
  case (1 n)
  note IH = this
  then show ?case 
    proof(cases rule: equ.cases[OF nabla  t  swap pi t])
      case (1 b c nabla t2 t1)
        have deptht1: "depth t1 < n"
          using 1 depth.simps(4) IH by simp
        have swap_pi_t1_is_t2: "swap pi t1 = t2"
          using 1(2,3) by auto
        have swap_pi_b_is_c: "swapas pi b = c"
          using 1(2,3) by auto
        with swap_pi_t1_is_t2 have "nabla  t1  swap [(b, swapas pi b)] (swap pi t1)"
          using 1(1,6) by simp
        then have "nabla  t1  swap ([(b, swapas pi b)] @ pi) t1"
          using swap_append[of [(b, swapas pi b)] pi t1] by simp
        with deptht1 have " a  ds [] ((b, swapas pi b)#pi). nabla  a  t1"
          using "1.IH" 1 by auto
        then have ds_minus_bc: " a  ds [] pi - {b, c}. nabla  a  t1"
          using ds_equality swap_pi_b_is_c by auto
        have c_fresh_t1: "nabla  c  t1"
          using 1 equ_symm l3_jud fresh_swap_eqvt Equ_elims equ_abst_ab by meson
        with ds_minus_bc have " a  ds [] pi - {b}. nabla  a  t1"
          by auto
        then have ds_minus_b: " a  ds [] pi - {b}. nabla  a  Abst b t1"
          using fresh_abst_ab by blast
        have b_fresh_abst_t1: "nabla  b  Abst b t1"
          using fresh_abst_aa by simp
        have " a  ds [] pi. nabla  a  Abst b t1"
        proof(rule, goal_cases)
          case (1 a)
          then show ?case
            using b_fresh_abst_t1 ds_minus_b
            by (cases "a=b", auto)
        qed
        with 1 show ?thesis
          by auto
    next
      case (2 nabla t1 t2 b)
      have deptht1: "depth t1 < n"
        using 2 depth.simps(4) IH by simp
      have swap_pi_t1_is_t2: "swap pi t1 = t2"
        using 2(2,3) by auto
      from swap_pi_t1_is_t2 deptht1 
      have " a  ds [] pi. nabla  a  t1"
        using "1.IH" 2(1,4) by auto
      then show ?thesis 
        using 2(1,2,3) elem_ds by fastforce
    next
      case (3 nabla)
      then show ?thesis 
        by blast
    next
      case (4 a b nabla)
      then show ?thesis
        using elem_ds by force
    next
      case (5 pi1 pi2 X nabla)
      have "swap pi t = Susp (pi@pi1) X" 
        using "5"(2) by auto
      also have "... = Susp pi2 X"
        using 5(3) calculation by simp
      then have "pi@pi1 = pi2" by simp
      hence "cds pi1 (pi@pi1). (c, X)  nabla"
        using 5(4) by simp
      then show ?thesis 
        using "5"(1,2) fresh_susp ds_cancel_pi_right[of _ _ "[]" _]
        by simp
    next
      case (6 nabla t1 t2 s1 s2)
      have deptht1: "depth t1 < n"
        using 6 depth.simps(5) IH
        by simp
      have depths1: "depth s1 < n"
        using 6 depth.simps(5) IH
        by simp
      from deptht1 depths1 show ?thesis 
        using "1.IH" 6 by auto
    next
      case (7 nabla t1 t2 f)
      have deptht1: "depth t1 < n"
        using 7(2) depth.simps(5) IH 
        by auto
      have "nabla  t1  swap pi t1"
        using 7 by simp
      then have " a  ds [] pi. nabla  a  t1"
        using 7(1) IH deptht1 by simp
      then show ?thesis 
        using 7(1,2) fresh_func[of nabla _ t1 f] 
        by simp
    qed
  qed

(*<*)
end 
(*>*)