Theory Sorting

subsection ‹Sorting›

text ‹Some preliminary lemmas about sorting.›

theory Sorting
  imports Main "HOL.List" "HOL-Library.Sublist"
begin

lemma insort:
  assumes "Suc l < length s"
  assumes "s ! l < (v :: 'a :: linorder)"
  assumes "s ! (l+1) > v"
  assumes "sorted_wrt (<) s"
  shows "sorted_wrt (<) ((take (Suc l) s)@v#(drop (Suc l) s))"
proof -
  have "sorted_wrt (<) (take (Suc l) s@(drop (Suc l) s))"
    using assms(4) by simp
  moreover have
    "⋀x. x ∈ set (take (Suc l) s) = (∃i. i < (Suc l) ∧ i < length s ∧ s ! i = x)" 
    by (metis in_set_conv_nth length_take min_less_iff_conj nth_take)
  hence "⋀x. x ∈ set (take (Suc l) s) ⟹ x < v"
    using assms apply (simp) 
    using less_Suc_eq sorted_wrt_nth_less by fastforce
  moreover have
    "⋀x. x ∈ set (drop (Suc l) s) = (∃i. Suc l + i < length s ∧ s ! (Suc l + i) = x)"
    using assms(1) by (simp add:in_set_conv_nth add.commute less_diff_conv)
  hence "⋀x. x ∈ set (drop (Suc l) s) ⟹ x > v"
    using assms apply (simp) 
    by (metis add.right_neutral add_diff_cancel_left' diff_Suc_Suc diff_is_0_eq'
        leI le_less_trans less_imp_le sorted_wrt_iff_nth_less)
  ultimately show ?thesis
    by (simp add:sorted_wrt_append del:append_take_drop_id)
qed

lemma sorted_wrt_irrefl_distinct:
  assumes "irreflp r"
  shows "sorted_wrt r xs ⟶ distinct xs"
  using assms by (induction xs, simp, simp, meson irreflp_def)

lemma sort_set_unique_h:
  assumes "irreflp r ∧ transp r"
  assumes "set (x#xs) = set (y#ys)" 
  assumes "∀z ∈ set xs. r x z" 
  assumes "∀z ∈ set ys. r y z" 
  shows "x = y ∧ set xs = set ys"
  by (metis assms insert_eq_iff irreflp_def list.set_intros(1)
      list.simps(15) set_ConsD transpD)

lemma sort_set_unique_rel:
  assumes "irreflp r ∧ transp r"
  assumes "set x = set y"
  assumes "sorted_wrt r x"
  assumes "sorted_wrt r y"
  shows "x = y"
proof -
  have "length x = length y" 
    using assms by (metis sorted_wrt_irrefl_distinct distinct_card)
  then show ?thesis using assms 
    apply(induct rule:list_induct2, simp, simp)
    by (metis assms(1) list.simps(15) sort_set_unique_h) 
qed

lemma sort_set_unique:
  assumes "set x = set y"
  assumes "sorted_wrt (<) (map (f :: ('a ⇒ ('b :: linorder)))  x)"
  assumes "sorted_wrt (<) (map f y)"
  shows "x = y"
  using assms apply (simp add:sorted_wrt_map) 
  by (metis (no_types, lifting) irreflp_def less_irrefl sort_set_unique_rel 
      transpD transpI transp_on_less)

text ‹If two sequences contain the same element and strictly increasing with respect.›

lemma subseq_imp_sorted:
  assumes "subseq s t"
  assumes "sorted_wrt p t"
  shows "sorted_wrt p s"
proof -
  have "sorted_wrt p s ∨ ¬ sorted_wrt p t"
  apply (rule list_emb.induct[where P="(=)"])
  using list_emb_set assms by fastforce+
  thus ?thesis using assms by blast
qed

text ‹If a sequence @{text t} is sorted with respect to a relation @{text p} then a subsequence will 
  be as well.›

fun to_ord where "to_ord r x y = (¬(r** y x))"

lemma trancl_idemp: "r++++ x y = r++ x y" 
  by (metis r_into_rtranclp reflclp_tranclp rtranclp_idemp rtranclp_reflclp 
      rtranclp_tranclp_tranclp tranclp.cases tranclp.r_into_trancl)

lemma top_sort:
  fixes rp
  assumes "acyclicP r"
  shows "finite s ⟶ (∃l. set l = s ∧ sorted_wrt (to_ord r) l ∧ distinct l)"
proof (induction "card s" arbitrary:s)
  case 0
  then show ?case by auto
next
  case (Suc n)
  hence "s ≠ {}" by auto
  moreover 
  have "acyclicP (r++)" using assms
    by (simp add:acyclic_def trancl_def trancl_idemp)
  hence "acyclic ({(x,y). r++ x y} ∩ s × s)"
    by (meson acyclic_subset inf_le1)
  hence "wf ({(x,y). r++ x y} ∩ s × s)" using Suc 
    by (metis card.infinite finite_Int finite_SigmaI nat.distinct(1) 
        wf_iff_acyclic_if_finite)
  ultimately obtain z where 
    "z ∈ s ∧ (∀y. (y, z) ∈  ({(x,y). r++ x y} ∩ s × s) ⟶ y ∉ s)" 
    by (metis ex_in_conv wf_eq_minimal)
  hence z_def: "z ∈ s ∧ (∀y. r++ y z ⟶ y ∉ s)" by blast
  hence "card (s - {z}) = n"
    by (metis One_nat_def Suc.hyps(2) card_Diff_singleton_if card.infinite 
        diff_Suc_Suc diff_zero nat.simps(3))
  then obtain l where l_def: 
    "set l = s - {z} ∧ sorted_wrt (to_ord r) l ∧ distinct l" 
    by (metis Zero_not_Suc card.infinite finite_Diff Suc)
  hence "set (z#l) = s" using z_def by auto
  moreover have "∀y ∈ set l. ¬(r** y z)" using z_def l_def rtranclpD by force
  ultimately show ?case 
    by (metis distinct.simps(2) insert_absorb l_def list.simps(15) 
        sorted_wrt.simps(2) to_ord.elims(3))
qed

lemma top_sort_eff:
  assumes "irreflp p++"
  assumes "sorted_wrt (to_ord p) x" 
  assumes "i < length x"
  assumes "j < length x"
  assumes "(p++ (x ! i) (x ! j))"
  shows "i < j"
  using assms apply (cases "i > j")
   apply (metis sorted_wrt_nth_less r_into_rtranclp reflclp_tranclp
          rtranclp_idemp rtranclp_reflclp to_ord.simps)
  by (metis irreflp_def nat_neq_iff)

end