Theory More_Lists

theory More_Lists
  imports Main
begin

lemma list_2_preds_aux:
  "x'  set xs; P1 x'; xs1 x xs2. xs = xs1 @ [x] @ xs2; P1 x 
      ys1 y ys2. x # xs2 = ys1 @ [y] @ ys2  P2 y  
      xs1 x xs2. xs = xs1 @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y)"
proof(goal_cases)
  case assms: 1

  define property 
       where "property xs =
                (xs2 xs1 x. (xs = xs1 @ [x] @ xs2  P1 x) 
                   (ys1 y ys2. x#xs2 = ys1 @ [y] @ ys2  P2 y))"
       for xs

  have propE: "property xs;
               (xs1 x xs2. xs = xs1 @ [x] @ xs2; P1 x 
                  ys1 y ys2. x#xs2 = ys1 @ [y] @ ys2  P2 y)  P
               P" for xs P
    by(auto simp add: property_def)

  have property_append: "property (xs @ ys)  property ys" for xs ys
    by(auto simp: property_def)

  have "property xs"
    using assms(3)
    by (force simp: property_def)



  thus  ?thesis
    using assms(1,2)
  proof(induction xs arbitrary: x')
    case Nil
    then show ?case 
      by auto
  next
    case (Cons a xs)
    hence "property xs" 
      by(auto intro: property_append[where xs = "[a]"])

    show ?case
    proof(cases "x' = a")
      case x_eq_a: True

      then obtain ys1 y ys2 where "x'#xs = ys1 @ [y] @ ys2" "P2 y"
        using property (a # xs) P1 x'
        apply(elim propE)
        by (auto 10 10)

      show ?thesis
      proof(cases "ys1 = []")
        case ys1_empty: True
        hence "xs = ys2"
          using x'#xs = ys1 @ [y] @ ys2
          by auto
        then show ?thesis
        proof(cases "xset ys2. P1 x")
          case x_in_ys2: True
          then obtain x where "x  set ys2" "P1 x"
            by auto
          hence "xs1 x xs2. xs = xs1 @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y)"
            using property xs xs = ys2 P2 y
            apply(intro Cons(1))
            by auto
          then obtain xs1 x xs2 where "(a # xs) = (a #xs1) @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y)"
            by auto
          then show ?thesis
            by metis
        next
          case x_notin_ys2: False
          hence "a # xs = a#ys2  P2 y  (yset ys2. ¬ P1 y)"
            using xs = ys2 P2 y
            by auto
          then show ?thesis
            using x' # xs = ys1 @ [y] @ ys2 x_eq_a
            by blast
        qed
      next
        case ys2_nempty: False
        then obtain ys1' where "xs = ys1' @ [y] @ ys2"
          using x'#xs = ys1 @ [y] @ ys2
          by (auto simp: neq_Nil_conv)
        show ?thesis
        proof(cases "xset ys2. P1 x")
          case x_in_ys2: True
          then obtain x where "x  set ys2" "P1 x"
            by auto
          hence "xs1 x xs2. xs = xs1 @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y)"
            using property xs xs = ys1' @ [y] @ ys2 P2 y
            apply(intro Cons(1))
            by auto
          then obtain xs1 x xs2 where "(a # xs) = (a #xs1) @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y)"
            by auto
          then show ?thesis
            by metis
        next
          case x_notin_ys2: False
          hence "a # xs = (a# ys1') @ [y] @ ys2  P2 y  (yset ys2. ¬ P1 y)"
            using xs = ys1' @ [y] @ ys2 P2 y
            by auto
          then show ?thesis
            by metis
        qed
      qed
    next
      case x_neq_a: False
      hence "x'  set xs"
        using Cons
        by auto
      then obtain xs1 x xs2 where "xs = xs1 @ [x] @ xs2" "P2 x" "(yset xs2. ¬ P1 y)"
        using Cons property xs
        by blast
      hence "a # xs = (a # xs1) @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y)"
        by auto
      thus ?thesis
        by metis
    qed
  qed
qed

lemma list_2_preds:
  " xset xs; P1 x; xs1 x xs2. xs = xs1 @ [x] @ xs2; P1 x  ys1 y ys2. x#xs2 = ys1 @ [y] @ ys2  P2 y  
      xs1 x xs2. xs = xs1 @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y  ¬ P2 y)"
proof(goal_cases)
  case assms: 1
  hence "xs1 x xs2. xs = xs1 @ [x] @ xs2  P2 x  (yset xs2. ¬ P1 y)"
    by (fastforce intro!: list_2_preds_aux)
  then obtain xs1 x xs2 where "xs = xs1 @ [x] @ xs2" "P2 x" "(yset xs2. ¬ P1 y)"
    by auto
  hence "ys1 y ys2. x # xs2 = ys1 @ [y] @ ys2  P2 y  (zset ys2. ¬ P2 z)"
    by (auto intro!: split_list_last_prop)
  then obtain ys1 y ys2 where "x # xs2 = ys1 @ [y] @ ys2" "P2 y" "(zset ys2. ¬ P2 z)"
    by auto
  hence "(zset ys2. ¬P1 z  ¬ P2 z)"
    using (yset xs2. ¬ P1 y) P2 x
    by (metis Un_iff insert_iff list.simps(15) set_append)
  moreover have "xs = (xs1 @ ys1) @ [y] @ ys2"
    using xs = xs1 @ [x] @ xs2 x # xs2 = ys1 @ [y] @ ys2
    by auto
  ultimately show ?case
    using P2 y
    by fastforce
qed

lemma list_inter_mem_iff: "set xs  s  {}  (xs1 x xs2. xs = xs1 @ [x] @ xs2  x  s)"
  by (metis append.left_neutral append_Cons disjoint_iff in_set_conv_decomp)
end