Section SumList.
Variable A : Set.
Definition sumList(ls : list A)(f : A -> Rat) := fold_left (fun a b => a + (f b)) ls 0.
(* Facts about sumList *)
Abort.
Abort.
induction ls; intuition; simpl in *.
eapply eqRat_refl.
eapply eqRat_trans.
eapply IHls.
eapply eqRat_trans.
eapply ratAdd_assoc.
eapply ratAdd_eqRat_compat.
eapply eqRat_refl.
eapply eqRat_symm.
eapply IHls.
Qed.
induction ls; intuition; simpl in *.
eapply IHls; eauto.
eapply ratAdd_eqRat_compat; eauto.
Qed.
induction 1; intuition; simpl in *.
eapply IHPermutation; eauto.
eapply ratAdd_eqRat_compat; eauto.
eapply fold_add_body_eq.
eapply eqRat_trans.
eapply ratAdd_assoc.
eapply eqRat_trans.
2:{
eapply eqRat_symm.
eapply ratAdd_assoc.
}
eapply ratAdd_eqRat_compat; eauto.
eapply eqRat_trans.
eapply ratAdd_comm.
eapply ratAdd_eqRat_compat; eauto.
intuition.
eapply eqRat_trans; eauto.
eapply eqRat_trans.
eapply fold_add_body_eq.
eapply eqRat_symm; eauto.
intuition.
eapply eqRat_symm.
eapply H2.
eapply Permutation_in.
eapply Permutation_sym.
eauto.
eauto.
simpl.
eapply IHPermutation2.
trivial.
intuition.
eapply H2.
eapply Permutation_in.
eapply Permutation_sym.
eauto.
eauto.
Qed.
induction ls; intuition; simpl in *.
eapply IHls; eauto.
rewrite H0.
eapply ratAdd_eqRat_compat; eauto.
eapply eqRat_refl.
intuition.
Qed.
induction ls; intuition; simpl in *.
intuition.
unfold sumList.
simpl.
eapply eqRat_refl.
intuition; subst.
unfold sumList in *; simpl in *.
eapply eqRat_trans.
eapply ratAdd_0.
eapply eqRat_trans.
eapply ratAdd_comm.
eapply eqRat_trans.
eapply eqRat_symm.
eapply fold_add_init.
eapply eqRat_trans.
eapply fold_add_body_eq.
eapply ratAdd_comm.
intuition.
eapply eqRat_refl.
eapply H.
eapply eqRat_refl.
eapply IHls.
unfold sumList in *; simpl in *.
eapply ratAdd_0.
eapply eqRat_trans.
eapply eqRat_symm.
eapply fold_add_init.
eapply eqRat_trans.
eapply fold_add_body_eq.
eapply ratAdd_comm.
intuition.
eapply eqRat_refl.
eapply H.
trivial.
unfold sumList.
simpl.
eapply eqRat_trans.
eapply fold_add_body_eq.
eapply ratAdd_comm.
intuition.
eapply eqRat_refl.
eapply eqRat_trans.
eapply fold_add_init.
eapply ratAdd_0.
intuition.
unfold sumList in *.
eapply IHls.
intuition.
Qed.
induction ls; intuition; unfold sumList in *; simpl in *.
exfalso.
apply H.
eapply eqRat_refl.
destruct H.
intuition.
assert (f a + fold_left (fun r a => r + f a) ls 0 == 0 -> False).
intuition.
eapply H.
eapply eqRat_trans.
eapply fold_add_body_eq.
eapply ratAdd_comm.
intuition.
eapply eqRat_refl.
eapply eqRat_trans.
eapply fold_add_init.
trivial.
eapply ratAdd_nz in H0.
destruct H0.
econstructor; intuition.
apply IHls in H0.
destruct H0; intuition.
exists x.
intuition.
assert (f a + fold_left (fun r a => r + f a) ls 0 == 0).
eapply eqRat_trans.
eapply eqRat_symm.
eapply fold_add_init.
eapply eqRat_trans.
eapply fold_add_body_eq.
eapply ratAdd_comm.
intuition.
eapply eqRat_refl.
trivial.
apply ratAdd_0 in H1.
intuition.
destruct H.
intuition.
subst.
intuition.
apply IHls in H3; intuition.
econstructor; eauto.
Qed.
End SumList.
intuition.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
rewrite ratAdd_0_r.
apply eqRat_refl.
apply eqRat_refl.
apply fold_add_init.
Qed.
induction ls; intuition; simpl in *; intuition.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_r.
apply eqRat_refl.
apply eqRat_refl.
trivial.
Qed.
intuition.
eapply eqRat_trans.
eapply fold_add_body_eq.
apply eqRat_refl.
eapply H.
simpl.
eapply fold_add_eq_init.
Qed.
induction ls; intuition; simpl in *.
eapply eqRat_refl.
rewrite IHls.
eapply fold_add_body_eq.
repeat rewrite <- ratAdd_assoc.
apply ratAdd_eqRat_compat; intuition.
rewrite ratAdd_assoc.
rewrite ratAdd_assoc.
apply ratAdd_eqRat_compat; intuition.
eapply ratAdd_comm.
intuition.
Qed.
induction lsa; destruct lsb; intuition; simpl in *; intuition.
apply eqRat_symm.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_r.
apply eqRat_refl.
apply eqRat_refl.
apply fold_add_eq_init.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_r.
apply eqRat_refl.
apply eqRat_refl.
apply fold_add_eq_init.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_l.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_l.
apply eqRat_refl.
apply eqRat_refl.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_l.
apply eqRat_refl.
apply eqRat_refl.
simpl.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
eapply eqRat_refl.
eapply fold_add_init_0.
simpl.
eapply eqRat_trans.
eapply fold_add_init_0.
eapply eqRat_trans.
eapply ratAdd_eqRat_compat.
apply eqRat_refl.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
apply ratAdd_0_r.
apply eqRat_refl.
apply eqRat_symm.
eapply fold_add_eq.
eapply eqRat_trans.
eapply ratAdd_eqRat_compat.
apply eqRat_refl.
apply ratAdd_eqRat_compat.
apply eqRat_refl.
eapply IHlsa.
eapply eqRat_symm.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_l.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_l.
apply eqRat_refl.
apply eqRat_refl.
eapply fold_add_body_eq; intuition.
rewrite <- ratAdd_0_l.
apply eqRat_refl.
apply eqRat_refl.
simpl.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
eapply eqRat_refl.
eapply fold_add_init_0.
simpl.
eapply eqRat_trans.
eapply fold_add_init_0.
eapply eqRat_trans.
eapply ratAdd_eqRat_compat.
apply eqRat_refl.
eapply eqRat_trans.
eapply fold_add_body_eq; intuition.
apply ratAdd_0_r.
apply eqRat_refl.
apply eqRat_symm.
eapply fold_add_eq.
eapply eqRat_trans.
eapply ratAdd_eqRat_compat.
eapply fold_add_init_0.
eapply eqRat_refl.
eapply eqRat_symm.
eapply eqRat_trans.
eapply ratAdd_eqRat_compat.
eapply fold_add_init_0.
eapply eqRat_refl.
repeat rewrite <- ratAdd_assoc.
eapply ratAdd_eqRat_compat.
repeat rewrite (ratAdd_assoc (f a b)).
eapply ratAdd_eqRat_compat; intuition.
eapply ratAdd_comm.
eapply eqRat_refl.
Qed.
intuition.
eapply fold_add_comm; intuition.
Qed.
intuition.
eapply fold_add_body_eq; intuition.
Qed.
induction ls; intuition; simpl in *.
intuition.
eapply eqRat_trans.
eapply fold_add_body_eq.
eapply eqRat_symm.
eapply ratMult_distrib_r.
intuition.
eapply eqRat_refl.
eapply IHls.
Qed.
intuition.
unfold sumList.
rewrite <- fold_add_factor_constant_r.
eapply fold_add_body_eq.
eapply eqRat_symm.
eapply ratMult_0_l.
intuition.
Qed.
intuition.
eapply eqRat_trans.
eapply sumList_body_eq; intuition.
apply ratMult_comm.
eapply eqRat_trans.
eapply sumList_factor_constant_r.
apply ratMult_comm.
Qed.
induction ls; intuition; simpl in *.
eapply eqRat_trans.
eapply ratAdd_0_l.
eapply ratAdd_eqRat_compat.
eapply eqRat_symm.
apply ratMult_0_r.
intuition.
rewrite IHls.
eapply eqRat_trans.
eapply ratAdd_eqRat_compat.
apply eqRat_refl.
apply ratAdd_comm.
rewrite <- (ratAdd_assoc).
apply ratAdd_eqRat_compat; intuition.
eapply eqRat_symm.
eapply eqRat_trans.
eapply ratMult_eqRat_compat.
apply eqRat_refl.
apply ratS_num.
rewrite ratMult_distrib.
rewrite ratAdd_comm.
apply ratAdd_eqRat_compat; intuition.
apply ratMult_1_r.
Qed.
intuition.
eapply eqRat_trans.
apply fold_add_body_const.
rewrite <- ratAdd_0_r.
eapply eqRat_refl.
Qed.
induction ls; intuition; simpl in *;
intuition; subst.
assert (init + f a <= r).
eapply IHls.
apply H.
eapply ratAdd_any_le; eauto.
assert (init + f a0 <= r).
eapply IHls.
eauto.
eapply ratAdd_any_le.
eapply leRat_trans.
apply eqRat_impl_leRat.
apply ratAdd_comm.
eauto.
edestruct IHls; eauto.
Qed.
intuition.
eapply fold_add_iter_le; eauto.
Qed.
Fixpoint removeFirst(A : Set)(eqd : eq_dec A)(ls : list A) a :=
match ls with
| nil => nil
| a' :: ls' =>
if (eqd a a') then ls' else a' :: (removeFirst eqd ls' a)
end.
induction ls; intuition; simpl in *;
intuition; subst.
destruct (eqd a0 a0); try congruence.
eapply Permutation_refl.
destruct (eqd a0 a); subst.
eapply Permutation_refl.
eapply perm_trans; [idtac | eapply perm_swap].
eapply perm_skip.
eauto.
Qed.
induction ls; intuition; simpl in *.
destruct (eqd a2 a); subst.
intuition.
simpl in *.
intuition.
eapply IHls; eauto.
Qed.
induction ls; intuition; simpl in *.
inversion H; clear H; subst.
destruct(eqd a0 a); subst.
intuition.
simpl in *.
intuition; subst.
eapply IHls; eauto.
Qed.

Lemma removeFirst_NoDup : forall (A : Set)(eqd : eq_dec A)(ls : list A) a,
NoDup ls ->
NoDup (removeFirst eqd ls a).