Theory List-Interleavings

theory List-Interleavings
imports Main
theory "List-Interleavings"
imports Main
begin

inductive interleave' :: "'a list ⇒ 'a list ⇒ 'a list ⇒ bool" 
  where [simp]: "interleave' [] [] []"
  | "interleave' xs ys zs ⟹interleave' (x#xs) ys (x#zs)"
  | "interleave' xs ys zs ⟹interleave' xs (x#ys) (x#zs)"

definition interleave :: "'a list ⇒ 'a list ⇒ 'a list set" (infixr "⊗" 64)
  where "xs ⊗ ys = Collect (interleave' xs ys)"
lemma elim_interleave'[pred_set_conv]: "interleave' xs ys zs ⟷ zs ∈ xs ⊗ ys" unfolding interleave_def by simp

lemmas interleave_intros[intro?] = interleave'.intros[to_set]
lemmas interleave_intros(1)[simp]
lemmas interleave_induct[consumes 1, induct set: interleave, case_names Nil left right] = interleave'.induct[to_set]
lemmas interleave_cases[consumes 1, cases set: interleave] = interleave'.cases[to_set]
lemmas interleave_simps = interleave'.simps[to_set]


inductive_cases interleave_ConsE[elim]: "(x#xs) ∈ ys ⊗ zs"
inductive_cases interleave_ConsConsE[elim]: "xs ∈ y#ys ⊗ z#zs"
inductive_cases interleave_ConsE2[elim]: "xs ∈ x#ys ⊗ zs"
inductive_cases interleave_ConsE3[elim]: "xs ∈ ys ⊗ x#zs"

lemma interleave_comm: "xs ∈ ys ⊗ zs ⟹ xs ∈ zs ⊗ ys"
  by (induction rule: interleave_induct) (auto intro: interleave_intros)

lemma interleave_Nil1[simp]: "[] ⊗ xs = {xs}"
  by (induction xs) (auto intro: interleave_intros elim: interleave_cases)

lemma interleave_Nil2[simp]: "xs ⊗ [] = {xs}"
  by (induction xs) (auto intro: interleave_intros elim: interleave_cases)

lemma interleave_nil_simp[simp]: "[] ∈ xs ⊗ ys ⟷ xs = [] ∧ ys = []"
  by (auto elim: interleave_cases)

lemma append_interleave: "xs @ ys ∈ xs ⊗ ys"
  by (induction xs) (auto intro: interleave_intros)

lemma interleave_assoc1: "a ∈ xs ⊗ ys ⟹ b ∈ a ⊗ zs ⟹ ∃ c. c ∈ ys ⊗ zs ∧  b ∈ xs  ⊗ c"
  by (induction b arbitrary: a  xs ys zs)
     (simp, fastforce del: interleave_ConsE elim!: interleave_ConsE  intro: interleave_intros)

lemma interleave_assoc2: "a ∈ ys ⊗ zs ⟹ b ∈ xs ⊗ a ⟹ ∃ c. c ∈ xs ⊗ ys ∧  b ∈ c ⊗ zs"
  by (induction b arbitrary: a  xs ys zs )
     (simp, fastforce del: interleave_ConsE elim!: interleave_ConsE  intro: interleave_intros)

lemma interleave_set: "zs ∈ xs ⊗ ys ⟹ set zs = set xs ∪ set ys"
  by(induction rule:interleave_induct) auto

lemma interleave_tl: "xs ∈ ys ⊗ zs ⟹ tl xs ∈ tl ys ⊗ zs ∨ tl xs ∈ ys ⊗ (tl zs)"
  by(induction rule:interleave_induct) auto

lemma interleave_butlast: "xs ∈ ys ⊗ zs ⟹ butlast xs ∈ butlast ys ⊗ zs ∨ butlast xs ∈ ys ⊗ (butlast zs)"
  by (induction rule:interleave_induct) (auto intro: interleave_intros)

lemma interleave_take: "zs ∈ xs ⊗ ys ⟹ ∃ n1 n2. n = n1 + n2 ∧  take n zs ∈ take n1 xs ⊗ take n2 ys"
  apply(induction arbitrary: n rule:interleave_induct)
  apply auto
  apply arith
  apply (case_tac n, simp)
  apply (drule_tac x = nat in meta_spec)
  apply auto
  apply (rule_tac x = "Suc n1" in exI)
  apply (rule_tac x = "n2" in exI)
  apply (auto intro: interleave_intros)[1]

  apply (case_tac n, simp)
  apply (drule_tac x = nat in meta_spec)
  apply auto
  apply (rule_tac x = "n1" in exI)
  apply (rule_tac x = "Suc n2" in exI)
  apply (auto intro: interleave_intros)[1]
  done

lemma filter_interleave: "xs ∈ ys ⊗ zs ⟹ filter P xs ∈ filter P ys ⊗ filter P zs"
  by (induction rule: interleave_induct)  (auto intro: interleave_intros)

lemma interleave_filtered: "xs ∈ interleave (filter P xs)  (filter (λx'. ¬ P x') xs)"
  by (induction xs) (auto intro: interleave_intros)


function foo where 
  "foo [] [] = undefined"
| "foo xs [] = undefined"
| "foo [] ys = undefined"
| "foo (x#xs) (y#ys) = undefined (foo xs (y#ys)) (foo (x#xs) ys)"
by pat_completeness auto
termination by lexicographic_order
lemmas list_induct2'' = foo.induct[case_names NilNil ConsNil NilCons ConsCons]

lemma interleave_filter:
  assumes "xs ∈ filter P ys ⊗ filter P zs"
  obtains xs' where "xs' ∈ ys ⊗ zs" and "xs = filter P xs'"
using assms
apply atomize_elim
proof(induction ys zs arbitrary: xs rule: list_induct2'')
case NilNil
  thus ?case by simp
next
case (ConsNil ys xs)
  thus ?case by auto
next
case (NilCons zs xs)
  thus ?case by auto
next
case (ConsCons y ys z zs xs)
  show ?case
  proof(cases "P y")
  case False
    with ConsCons.prems(1)
    have "xs ∈ filter P ys ⊗ filter P (z#zs)" by simp
    from ConsCons.IH(1)[OF this]
    obtain xs' where "xs' ∈ ys ⊗ (z # zs)" "xs = filter P xs'" by auto
    hence "y#xs' ∈ y#ys ⊗ z#zs" and "xs = filter P (y#xs')"
      using False by (auto intro: interleave_intros)
    thus ?thesis by blast
  next
 case True
    show ?thesis
    proof(cases "P z")
    case False
      with ConsCons.prems(1)
      have "xs ∈ filter P (y#ys) ⊗ filter P zs" by simp
      from ConsCons.IH(2)[OF this]
      obtain xs' where "xs' ∈ y#ys ⊗ zs" "xs = filter P xs'" by auto
      hence "z#xs' ∈ y#ys ⊗ z#zs" and "xs = filter P (z#xs')"
        using False by (auto intro: interleave_intros)
      thus ?thesis by blast
    next
    case True
      from ConsCons.prems(1) `P y` `P z`
      have "xs ∈ y # filter P ys  ⊗ z # filter P zs"  by simp
      thus ?thesis 
      proof(rule interleave_ConsConsE)
        fix xs'
        assume "xs = y # xs'" and "xs' ∈ interleave (filter P ys) (z # filter P zs)"
        hence "xs' ∈ filter P ys  ⊗ filter P (z#zs)" using `P z` by simp
        from ConsCons.IH(1)[OF this]
        obtain xs'' where "xs'' ∈ ys ⊗ (z # zs)" and "xs' = filter P xs''" by auto
        hence "y#xs'' ∈ y#ys  ⊗ z#zs" and "y#xs' = filter P (y#xs'')"
          using `P y` by (auto intro: interleave_intros)
        thus ?thesis using `xs = _` by blast
      next
        fix xs'
        assume "xs = z # xs'" and "xs' ∈ y # filter P ys  ⊗ filter P zs"
        hence "xs' ∈ filter P (y#ys) ⊗ filter P zs" using `P y` by simp
        from ConsCons.IH(2)[OF this]
        obtain xs'' where "xs'' ∈ y#ys ⊗ zs" and "xs' = filter P xs''" by auto
        hence "z#xs'' ∈ y#ys ⊗ z#zs" and "z#xs' = filter P (z#xs'')"
          using `P z` by (auto intro: interleave_intros)
        thus ?thesis using `xs = _` by blast
      qed
    qed
  qed
qed


end