Section Uqs_ind.
Variable P: list (Index e ol) -> M (list (Index e ol)) -> Prop.
Hypothesis Pnil: P nil (ret nil).
Hypothesis Pcons: forall n (v: Vector.t (Index e ol) (S n)),
(forall x0 cr, P (filter (fun f: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f (vec.nth v x0)) cr)) (vec.to_list (vec.remove v x0))) (qs cmp pick (filter (fun f: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f (vec.nth v x0)) cr)) (vec.to_list (vec.remove v x0))))) ->
P (vec.to_list v)
(ne_tree.Node
(ne_list.map
(fun x0: natBelow (S n) =>
ne_tree.map
(map_fst (C:=list (Index e ol)) (app (map (fun i0: Index e ol => unordered_nat_pair i0 (vec.nth v x0)) (vec.to_list (vec.remove v x0)))))
(foo <- qs cmp pick (filter (fun f: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f (vec.nth v x0)) Lt)) (vec.to_list (vec.remove v x0)));
bar <- qs cmp pick (filter (fun f: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f (vec.nth v x0)) Gt)) (vec.to_list (vec.remove v x0)));
ret (foo ++ (vec.nth v x0 :: filter (fun f0: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f0 (vec.nth v x0)) Eq)) (vec.to_list (vec.remove v x0))) ++ bar)))
(ne_list.from_vec (vec.nats 0 (S n))))).
Proof with auto.
apply qs_parts.rect...
apply Mext.
intros.
unfold qs_parts.body.
replace (qs_parts.selectPivotPart M pick cmp v) with (ne_tree.Node (ne_list.map (fun x0: natBelow (S n) => ne_tree.map (map_fst (app (map (fun i0: Index e ol => unordered_nat_pair i0 ((vec.nth v x0))) (vec.to_list (vec.remove v x0))))) (
foo <- qs cmp pick (filter (fun f: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f (vec.nth v x0)) Lt)) (vec.to_list (vec.remove v x0)));
bar <- qs cmp pick (filter (fun f: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f (vec.nth v x0)) Gt)) (vec.to_list (vec.remove v x0)));
ret (m:=ne_tree_monad.M) (nil, foo ++ (vec.nth v x0 :: filter (fun f0: Index e ol => unsum_bool (cmp_cmp (Ecmp (UE e ol) f0 (vec.nth v x0)) Eq)) (vec.to_list (vec.remove v x0))) ++ bar))) (ne_list.from_vec (vec.nats 0 (S n))))).
simpl @ret in Pcons.
Focus 1.
specialize (Pcons v).
simpl vec.to_list in Pcons.
apply Pcons. clear Pcons.
intros.
apply H.
rewrite length_filter.
apply le_lt_trans with (length (vec.to_list (vec.remove v x0))).
apply count_le.
rewrite vec.length...
unfold qs_parts.selectPivotPart.
unfold qs_parts.partitionPart.
unfold qs_parts.lowRecPart.
simpl.
f_equal.
repeat rewrite ne_list.map_map.
apply ne_list.map_ext. intro.
unfold compose. simpl.
rewrite ne_tree_monad.map_bind.
rewrite (@mon_assoc (ne_tree_monad.M)).
rewrite partition. simpl.
rewrite (@mon_assoc (ne_tree_monad.M)). simpl.
rewrite (@mon_assoc (ne_tree_monad.M)). simpl.
rewrite (@simplePartition_component (UE e ol)).
apply ne_tree_monad.ext. intro.
rewrite (@mon_assoc (ne_tree_monad.M)). simpl.
rewrite ne_tree_monad.map_bind.
rewrite (@mon_assoc (ne_tree_monad.M)). simpl.
rewrite (@mon_assoc (ne_tree_monad.M)). simpl.
rewrite (@simplePartition_component (UE e ol)).
apply ne_tree_monad.ext. intro.
unfold compose, map_fst.
simpl.
rewrite (@simplePartition_component (UE e ol)).
reflexivity.
Qed.
End Uqs_ind.
Proof with auto.
intros.
destruct x.
destruct y.
destruct (eq_nat_dec n n1).
destruct (eq_nat_dec n0 n2).
subst.
left...
right. intro. inversion H...
right. intro. inversion H...
Qed.
Definition UcmpCmp (x y: nat * nat): bool := unsum_bool (UcmpDec x y).
Definition ijcount (i j: nat): monoid -> nat := count (UcmpCmp (i, j)).
Proof with auto.
unfold ijcount.
intros.
apply count_0.
intros.
unfold UcmpCmp.
case_eq (UcmpDec (i, j) x); intros...
elimtype False.
apply H.
rewrite e0...
Qed.

Lemma hom_ijcount i j: monoidHomo monoid NatAddMonoid (ijcount i j).