(* ========================================================================= *)
(*  Quick sort algorithm.                                                    *)
(*                                                                           *)
(*  Author: Marco Maggesi                                                    *)
(*          University of Florence, Italy                                    *)
(*          http://www.math.unifi.it/~maggesi/                               *)
(*                                                                           *)
(*          (c) Copyright, Marco Maggesi, 2005-2007                          *)
(* ========================================================================= *)
needs "Permutation/permuted.ml";;
(* ------------------------------------------------------------------------- *)
(* Ordered lists.                                                            *)
(* ------------------------------------------------------------------------- *)
let ORDERED_RULES, ORDERED_INDUCT, ORDERED_CASES = new_inductive_definition
  `(!le. ORDERED le []) /\
   (!le h t. ORDERED le t /\ ALL (le h) t ==> ORDERED le (CONS h t))`;;
let ORDERED_CONS = prove
  (`!le (h:A) t. ORDERED le (h :: t) <=> (ORDERED le t /\ 
ALL (le h) t)`,
   SUBGOAL_THEN
    `!le (h:A) t. ORDERED le (h :: t) ==> (ORDERED le t /\ 
ALL (le h) t)`
   (fun th -> MESON_TAC [th; ORDERED_RULES]) THEN
   REPEAT GEN_TAC THEN
   DISCH_THEN (MP_TAC o ONCE_REWRITE_RULE [ORDERED_CASES]) THEN
   REWRITE_TAC [
NOT_CONS_NIL; 
CONS_11] THEN MESON_TAC []);;
 
 
let ORDERED_APPEND = prove
 (`!l1 l2:A list.
      ORDERED le (
APPEND l1 l2) <=>
      ORDERED le l1 /\ ORDERED le l2 /\ 
ALL (\x. 
ALL (le x) l2) l1`,
  SUBGOAL_THEN
    `(!l1 l2:A list.
        ORDERED le (
APPEND l1 l2)
        ==> ORDERED le l1 /\ ORDERED le l2 /\ 
ALL (\x. 
ALL (le x) l2) l1) /\
     (!l1 l2. ORDERED le l1 /\ ORDERED le l2 /\ 
ALL (\x. 
ALL (le x) l2) l1
              ==> ORDERED le (
APPEND l1 l2))`
   (fun th -> MESON_TAC [th]) THEN
   CONJ_TAC THEN LIST_INDUCT_TAC THEN
   REWRITE_TAC [
APPEND; 
ALL; ORDERED_RULES; 
ORDERED_CONS] THEN
   ASM_SIMP_TAC [
ORDERED_CONS; 
ALL_APPEND] THEN ASM_MESON_TAC [
ALL_APPEND]);;
 
 
(* ------------------------------------------------------------------------- *)
(*  Quick Sort.                                                              *)
(* ------------------------------------------------------------------------- *)
let QSORT =
  let PROVE_RECURSIVE_FUNCTION_EXISTS_TAC : tactic = fun g ->
    let th = pure_prove_recursive_function_exists (snd g) in
    MATCH_MP_TAC (DISCH_ALL th) g in
  new_specification ["QSORT"] (prove
  (`?f. (!le. f le [] = [] : A list) /\
        (!le h t. f le (CONS h t) =
                  APPEND (f le (FILTER (\x. ~le h x) t))
                  (CONS h (f le (FILTER (\x. le h x) t))))`,
   REWRITE_TAC [GSYM SKOLEM_THM; AND_FORALL_THM] THEN GEN_TAC THEN
   PROVE_RECURSIVE_FUNCTION_EXISTS_TAC THEN
   EXISTS_TAC `MEASURE (LENGTH:A list -> num)` THEN
   REWRITE_TAC [WF_MEASURE; MEASURE; LENGTH; FILTER] THEN
   REWRITE_TAC [LT_SUC_LE; LENGTH_FILTER_LE]));;
let ORDERED_QSORT = prove
 (`!le (l:A list).
     (!x y. le x y \/ le y x) /\ (!x y z. le x y \/ le y z ==> le x z)
     ==> ORDERED le (QSORT le l)`,
 
 
(* Example:
REWRITE_CONV [QSORT; ARITH_LE; ARITH_LT; FILTER; APPEND]
  `QSORT (<=) [12;3;5;1;23;2;1]`;;
*)