theory QSort imports Universe begin (* SPLITTING FUNCTION *) primrec qsplit :: "('a \ 'a \ bool) \ 'a :: universe \ 'a list \ 'a list" where "qsplit f p [] = []" | "qsplit f p (h # t) = (if f h p then h # qsplit f p t else qsplit f p t)" lemma qsplit_length [simp]: "length (qsplit f p l) \ length l" by (induct l, auto) (* QUICKSORT, i.e. the MODEL *) function qsort :: "'a :: universe list \ 'a list" where "qsort [] = []" | "qsort (p # l) = qsort (qsplit lt p l) @ p # qsort (qsplit ge p l)" by pat_completeness auto termination by (relation "measure length", auto, (metis le_imp_less_Suc qsplit_length)+) (* ORDER LIFTING TO LISTS, i.e. part of SPECIFICATION *) primrec qall :: "('a \ 'a \ bool) \ 'a \ 'a list \ bool" where "qall f p [] = True" | "qall f p (h # t) = (f h p \ qall f p t)" theorem qsplit_splits [simp]: "qall f p (qsplit f p l)" by (induct l, auto) lemma qall_concat [iff]: "qall f p (a @ b) = (qall f p a \ qall f p b)" by (induct a, auto) theorem qall_qsplit [simp]: "qall f p l \ qall f p (qsplit g q l)" by (induct l, auto) theorem qall_qsort [simp]: "qall f p l \ qall f p (qsort l)" by (induct l rule: qsort.induct, auto) (* SORTEDNESS, i.e. SPECIFICATION *) fun qsorted :: "'a :: universe list \ bool" where "qsorted [] = True" | "qsorted [x] = True" | "qsorted (a # b # l) = (ge b a \ qsorted (b # l))" lemma qsorted_append [simp]: "\ qsorted l; qall ge p l\ \ qsorted (p # l)" by (induct l, auto) theorem qsorted_concat [simp]: "\ qsorted a; qsorted b; qall lt p a; qall ge p b \ \ qsorted (a @ p # b)" by (induct a, simp, clarsimp, case_tac a2, auto) (* PERMUTATION, i.e. SPECIFICATION *) primrec count :: "'a list \ 'a \ nat" where "count [] = (\x. 0)" | "count (h # t) = (count t) (h := count t h + 1)" lemma count_concat [simp]: "count (a @ b) x = count a x + count b x" by (induct a, auto) theorem count_qsplit_lt_ge [iff]: "count (qsplit lt p l) x + count (qsplit ge p l) x = count l x" by (induct l, auto) (* CORE THEOREMS, i.e. consistency of model and specification *) theorem qsort_sorts: "qsorted (qsort l)" by (induct l rule: qsort.induct, auto) theorem qsort_preserves: "count (qsort l) = count l" by (induct l rule: qsort.induct, auto, rule ext, auto) end