theory EQSort imports Universe begin (* SPLITTING FUNCTION *) primrec qsplit :: "'a :: universe \ 'a list \ 'a list * 'a list" where "qsplit p [] = ([], [])" | "qsplit p (x # xr) = (let (below, above) = qsplit p xr in if ge x p then (below, x # above) else (x # below, above))" lemma qsplit_length_below [rule_format]: "\bl ab. (bl, ab) = qsplit p l \ length bl \ length l" apply (induct l, auto) apply (case_tac "qsplit p l", auto) apply (case_tac "lt a p", auto) done lemma qsplit_length_above [rule_format]: "\bl ab. (bl, ab) = qsplit p l \ length ab \ length l" apply (induct l, auto) apply (case_tac "qsplit p l", auto) apply (case_tac "lt a p", auto) done (* QUICKSORT, i.e. the MODEL *) function qsort :: "'a :: universe list \ 'a list" where "qsort [] = []" | "qsort (p # rest) = (let (below, above) = qsplit p rest in qsort below @ [p] @ qsort above)" by pat_completeness auto termination by (relation "measure length", auto dest: qsplit_length_above qsplit_length_below) (* 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_below [rule_format, simp]: "\bl ab. qsplit p l = (bl, ab) \ qall lt p bl" apply (induct l, auto) apply (case_tac "qsplit p l", auto) apply (case_tac "lt a p", auto) done theorem qsplit_splits_above [rule_format, simp]: "\bl ab. qsplit p l = (bl, ab) \ qall ge p ab" apply (induct l, auto) apply (case_tac "qsplit p l", auto) apply (case_tac "lt a p", auto) done lemma qall_concat [iff]: "qall f p (a @ b) = (qall f p a \ qall f p b)" by (induct a, auto) theorem qall_qsplit_below [rule_format, simp]: "\bl ab. (bl, ab) = qsplit q l \ qall f p l \ qall f p bl" apply (induct l, auto) apply (case_tac "qsplit q l", auto) apply (case_tac "lt a q", auto) done theorem qall_qsplit_above [rule_format, simp]: "\bl ab. (bl, ab) = qsplit q l \ qall f p l \ qall f p ab" apply (induct l, auto) apply (case_tac "qsplit q l", auto) apply (case_tac "lt a q", auto) done theorem qall_qsort [rule_format, intro!]: "qall f p l \ qall f p (qsort l)" apply (induct l rule: qsort.induct, auto) apply (case_tac "qsplit pa rest") apply force+ done (* 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 [intro!]: "\ 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 [rule_format, iff]: "\bl ab. (bl, ab) = qsplit p l \ count bl x + count ab x = count l x" apply (induct l, auto) apply (case_tac "qsplit p l", auto) apply (case_tac "lt x p", auto) apply (case_tac "qsplit p l", auto) apply (case_tac "lt a p", auto) done (* CORE THEOREMS, i.e. consistency of model and specification *) theorem qsort_sorts: "qsorted (qsort l)" apply (induct l rule: qsort.induct, auto) apply (case_tac "qsplit p rest", auto) apply force done theorem qsort_preserves: "count (qsort l) = count l" apply (induct l rule: qsort.induct, auto, rule ext, auto) apply (case_tac "qsplit p rest", auto) apply (metis count_concat count_qsplit_lt_ge) apply (case_tac "qsplit p rest", auto) apply (metis count_concat count_qsplit_lt_ge) done end