apply (well_founded_induction_type (Wf_nat.well_founded_ltof _ (@length X))).
intros.
unfold ltof in H.
destruct x.
unfold Basics.compose.
simpl.
rewrite Ravg_single...
rewrite Ceq...
rewrite (Ravg_Permutation (Permutation.Permutation_map (INR ∘ cost ∘ qs) (perms_alt_perms (e :: x)))).
unfold alt_perms.
set (e :: x) in *.
rename x into t. rename e into h.
rewrite map_concat.
rewrite map_map.
rewrite (@Ravg_concat (fact (pred (length l)))).
Focus 2.
intros.
destruct (fst (conj_prod (in_map_iff _ _ _)) H0).
destruct H1.
subst.
rewrite map_length.
rewrite map_length.
rewrite length_perms.
replace (length (snd x)) with (pred (S (length (snd x))))...
rewrite (length_in_splits _ _ H2)...
rewrite map_map.
replace (map
(fun x =>
Ravg (map (INR ∘ cost ∘ qs) (map (cons (fst x)) (perms (snd x)))))
(splits l))
with (map (fun x =>
Ravg (map (INR ∘ @length _) (perms (snd x))) +
Ravg (map (INR ∘ cost ∘ qs ∘ filter (Egtb (fst x))) (perms (snd x))) +
Ravg (map (INR ∘ cost ∘ qs ∘ filter (Eltb (fst x))) (perms (snd x)))
) (splits l)).
Focus 2.
apply map_ext.
intros.
rewrite map_map.
unfold Basics.compose.
replace (map (fun x => INR (cost (qs (fst a :: x)))) (perms (snd a))) with
(map (fun x => length x + cost (qs (filter (Egtb (fst a)) x)) + cost (qs (filter (Eltb (fst a)) x))) (perms (snd a))).
rewrite Ravg_map_plus.
rewrite Ravg_map_plus...
apply map_ext. intros.
rewrite (cost_qs (fst a :: a0)).
repeat rewrite plus_INR...
rewrite Ravg_map_plus.
rewrite Ravg_map_plus.
setoid_rewrite (avg_filter_perms (cost ∘ qs)).
replace (Ravg
(map (fun x => Ravg (map (INR ∘ @length _) (perms (snd x))))
(splits l))) with (INR (pred (length l))).
Focus 2.
symmetry.
apply Ravg_constant.
apply length_ne_0_ne_nil.
rewrite map_length, length_splits.
discriminate.
intros.
destruct (fst (conj_prod (in_map_iff _ _ _)) H0).
destruct H1.
subst.
apply Ravg_constant.
apply length_ne_0_ne_nil.
rewrite map_length, length_perms.
apply fact_neq_0.
intros.
destruct (fst (conj_prod (in_map_iff _ _ _)) H1).
destruct H3. subst.
unfold Basics.compose.
rewrite <- (length_in_splits _ _ H2).
rewrite (perms_are_perms _ _ H4)...
apply Rle_trans with
(pred (length l) +
Ravg (map (fun x => C (length (filter (Egtb (fst x)) (snd x)))) (splits l)) +
Ravg (map (fun x => C (length (filter (Eltb (fst x)) (snd x)))) (splits l))).
apply Rplus_le_compat...
apply Rplus_le_compat...
apply Ravg_map_le.
intros.
apply H...
apply le_lt_trans with (length (snd x)).
apply list_utils.length_filter_le.
rewrite <- (length_in_splits _ _ H0)...
apply Ravg_map_le.
intros.
apply H...
apply le_lt_trans with (length (snd x)).
apply list_utils.length_filter_le.
rewrite <- (length_in_splits _ _ H0)...
clear H.
rewrite Rplus_assoc.
rewrite <- (map_map (fun x => length (filter (Egtb (fst x)) (snd x))) C (splits l)).
rewrite <- (map_map (fun x => length (filter (Eltb (fst x)) (snd x))) C (splits l)).
rewrite <- (map_length_filter_permuted_splits (plain.isort_permutes Eleb l)).
rewrite <- (map_length_filter_permuted_splits (plain.isort_permutes Egeb l)).
unfold Ravg.
repeat rewrite map_length.
repeat rewrite length_splits.
rewrite (Permutation.Permutation_length (plain.isort_permutes Egeb l)).
rewrite (Permutation.Permutation_length (plain.isort_permutes Eleb l)).
unfold Rdiv.
rewrite <- Rmult_plus_distr_r.
apply Rle_trans with (pred (length l) +
(Rsum (map C (nats 0 (length l))) + Rsum (map C (nats 0 (length l)))) / length l).
apply Rplus_le_compat_l.
unfold Rdiv.
apply Rmult_le_compat_r...
apply Rlt_le, Rinv_0_lt_compat, (lt_INR 0 (S (length t)))...
apply Rplus_le_compat.
apply elemsR_le_Rsum.
apply elemsR_map' with le...
apply C_le_compat.
rewrite <- (Permutation.Permutation_length (plain.isort_permutes Eleb l)).
apply (@filtered_sort X Ele EO).
unfold Egtb, Ele.
intros.
destruct (Ecmp _ y x); try discriminate...
apply plain.isort_sorts'.
unfold Eleb. intros. rewrite Ecmp_sym. destruct Ecmp...
apply Eleb_preorder.
intros. apply <- (Eleb_true x y)...
apply elemsR_le_Rsum.
apply elemsR_map' with le...
apply C_le_compat.
rewrite <- (Permutation.Permutation_length (plain.isort_permutes Egeb l)).
apply (@filtered_sort X Ege Ege_preorder).
unfold Eltb, Ege.
intros.
destruct (Ecmp _ y x); try discriminate...
apply plain.isort_sorts'.
unfold Egeb.
intros. rewrite Ecmp_sym. destruct Ecmp...
apply Egeb_preorder.
intros. apply <- (Egeb_true x y)...
rewrite <- (Rmult_1_l (Rsum (map C (nats 0 (length l))))).
rewrite <- Rmult_plus_distr_r.
unfold Rdiv.
rewrite Rmult_assoc.
rewrite Ceq.
destruct (length l).
simpl.
rewrite Rmult_0_l.
fourier.
simpl pred.
unfold Rdiv.
apply Rplus_le_compat_l.
unfold Ravg. rewrite map_length. rewrite nats_length.
unfold Rdiv...
Qed.
(* The main result is now just a matter of sequencing the previous two lemmas. *)

(* Specifications: *)
Theorem qs_avg l: Ravg (map (INR ∘ cost ∘ qs) (perms l)) <= length l * 2 * log2ceil (length l).
Proof with auto with real.