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.
induction ls; intuition; simpl in *.
inversion H; clear H; subst.
destruct (eqd a0 a); subst.
trivial.
econstructor.
eapply removeFirst_not_in.
intuition.
eapply IHls; eauto.
Qed.
induction ls; intuition; simpl in *.
destruct (eqd a2 a); subst.
intuition.
congruence.
simpl.
intuition.
Qed.
induction ls; intuition; simpl in *.
destruct (eqd a2 a); subst.
intuition.
simpl in *.
intuition.
right.
eapply IHls; eauto.
Qed.
(* ls1 is the smaller set.  This function returns a permutation of ls2 where the first elements of ls2 match the order of the elements in ls1.  This function only works if ls1 is a subset of ls2. *)
Fixpoint matchOrder (A : Set)(eqd : eq_dec A)(ls1 ls2 : list A) :=
match ls1 with
| nil => ls2
| a :: ls1' =>
a :: (matchOrder eqd ls1' (removeFirst eqd ls2 a))
end.
induction ls1; destruct ls2; intuition; simpl in *; eauto; intuition; subst.
inversion H; clear H; subst.
inversion H0; clear H0; subst.
destruct (eqd a a1); subst.
intuition.
right.
eapply (IHls1 (a1 :: removeFirst _ ls2 a)); intuition.
econstructor.
eapply removeFirst_not_in; intuition.
eapply removeFirst_NoDup; intuition.
simpl.
destruct (H1 a0); auto.
right.
eapply removeFirst_in; eauto.
intuition. subst.
intuition.
inversion H; clear H; subst.
inversion H0; clear H0; subst.
destruct (H1 a); intuition; subst.
destruct (eqd a a); try congruence.
right.
eapply (IHls1 ls2); intuition.
destruct (H1 a0); intuition; subst.
intuition.
destruct (eqd a a0); try congruence.
destruct (eqd a a1); subst; auto.
right.
eapply (IHls1 (a0 :: removeFirst _ ls2 a)); intuition.
econstructor.
eapply removeFirst_not_in; trivial.
eapply removeFirst_NoDup; trivial.
simpl.
destruct (H1 a2); eauto.
destruct (eqd a0 a2); intuition.
right.
eapply removeFirst_in; trivial.
intuition.
subst.
intuition.
simpl.
destruct (eqd a0 a1); intuition.
right.
eapply removeFirst_in; trivial.
intuition.
inversion H; clear H; subst.
inversion H0; clear H0; subst.
destruct (eqd a0 a1); subst; intuition.
right.
assert (In a1 (if eqd a a0 then ls2 else a0 :: removeFirst eqd ls2 a)).
eapply IHls1.
trivial.
destruct (eqd a a0).
trivial.
econstructor.
eapply removeFirst_not_in; eauto.
eapply removeFirst_NoDup; intuition.
intuition.
destruct (eqd a a0).
destruct (H1 a2).
intuition.
subst.
intuition.
trivial.
simpl.
destruct (eqd a0 a2); intuition.
right.
destruct (H1 a2).
destruct (eqd a a2); intuition.
subst.
intuition.
eapply removeFirst_in.
trivial.
intuition. subst.
intuition.
trivial.
destruct (eqd a a0); intuition.
simpl in *.
intuition.
eapply removeFirst_in_iff.
eauto.
Qed.
induction ls1; intuition; simpl in *.
intuition; subst.
eapply (IHls1 (removeFirst eqd ls2 a)).
eapply H3.
intuition.
eapply removeFirst_not_in.
intuition.
eapply H0.
eauto.
eapply H.
eauto.
Qed.
induction ls1; intuition; simpl in *.
destruct (eqd a a0); subst;
intuition.
eapply IHls1.
intuition.
eapply H0.
assert (~ In a0 ls1).
intuition.
specialize (@matchOrder_not_in_h _ eqd ls1 (removeFirst eqd ls2 a) a0); intuition.
exfalso.
eapply H4; eauto.
intuition.
eapply removeFirst_not_in.
intuition.
eapply H0.
eapply H5.
eapply H3.
Qed.
induction ls1; intuition; simpl in *.
inversion H1; clear H1; subst.
econstructor.
eapply matchOrder_not_in.
intuition.
destruct (eqd a a0); subst; intuition.
eapply removeFirst_in.
eapply H.
intuition.
intuition.
eapply removeFirst_NoDup_not_in; eauto.
eapply IHls1; intuition.
destruct (eqd a a0); subst; intuition.
eapply removeFirst_in; eauto.
eapply removeFirst_NoDup; eauto.
Qed.
intuition.
eapply NoDup_Permutation; intuition.
eapply matchOrder_NoDup; eauto.
eapply (@matchOrder_In _ eqd ls1 ls2); eauto.
eapply (@matchOrder_In _ eqd ls1 ls2); eauto.
Qed.

Lemma matchOrder_firstn : forall (A : Set)(eqd : eq_dec A)(ls1 ls2 : list A),
NoDup ls1 ->
NoDup ls2 ->
(forall a, In a ls1 -> In a ls2) ->
firstn (length ls1) (matchOrder eqd ls1 ls2) = ls1.