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.
induction ls1; intuition; simpl in *.
inversion H; clear H; subst.
f_equal.
eapply IHls1; eauto.
eapply removeFirst_NoDup; eauto.
intuition.
destruct (eqd a0 a); subst; intuition.
eapply removeFirst_in.
eapply H1.
intuition.
intuition.
Qed.
induction ls; intuition; simpl in *.
destruct n; simpl in *;
trivial.
inversion H0; clear H0; subst.
destruct n; simpl in *.
eapply eqRat_symm.
eapply eqRat_trans.
eapply fold_add_eq_init_f; intuition.
rewrite (ratAdd_0_r init1).
eapply ratAdd_eqRat_compat; intuition.
eapply IHls.
eapply ratAdd_eqRat_compat; intuition.
trivial.
intuition.
eapply H1.
intuition.
intuition.
subst.
intuition.
Qed.
induction 1; intuition.
inversion H0; clear H0; subst.
econstructor.
intuition.
eapply H3.
eapply Permutation_in.
eapply Permutation_sym.
eapply H.
eauto.
eauto.
inversion H; clear H; subst.
inversion H3; clear H3; subst.
simpl in *.
econstructor.
simpl.
intuition.
econstructor;
intuition.
Qed.
intuition.
erewrite <- matchOrder_firstn at 1.
eapply eqRat_symm.
eapply eqRat_trans.
eapply fold_add_rat_perm.
eapply matchOrder_permutation.
eapply H0.
eauto.
intuition.
eapply eqRat_refl.
intuition.
eapply eqRat_refl.
eapply eqRat_symm.
eapply fold_add_matchOrder; intuition.
eapply permutation_NoDup.
eapply matchOrder_permutation; eauto.
eauto.
eapply H3.
intuition.
eapply H5.
rewrite matchOrder_firstn; eauto.
eauto.
eauto.
eauto.
Grab Existential Variables.
trivial.
Qed.
intuition.
eapply fold_add_subset; intuition.
Qed.
Fixpoint flatten(A : Type)(ls : list (list A)) :=
match ls with
| nil => nil
| a :: ls' => a ++ (flatten ls')
end.
induction ls; simpl in *; intuition.
destruct H; intuition.
apply in_app_or in H.
intuition.
exists a; intuition.
apply IHls in H0.
destruct H0.
intuition.
exists x; intuition.
apply in_or_app.
destruct H; intuition.
subst.
intuition.
right.
eapply IHls.
econstructor.
eauto.
Qed.
induction ls; destruct ls'; intuition; simpl in *.
intuition.
destruct H; simpl in *; subst; intuition.
destruct H; simpl in *; subst; intuition.
rewrite app_length.
simpl.
omega.
rewrite app_length.
specialize (IHls (a0 :: ls') H).
simpl in *.
intuition.
Qed.
Fixpoint getUnique(A : Set)(ls : list A)(pf : eq_dec A) : list A :=
match ls with
| nil => nil
| a :: ls' =>
let ls'' := (getUnique ls' pf) in
if (in_dec pf a ls'')
then ls''
else a :: ls''
end.
induction ls; simpl in *; intuition.
destruct (in_dec _ a (getUnique ls _)).
right.
eapply IHls.
eapply H.
simpl in *.
intuition.
right.
eapply IHls.
eapply H0.
Qed.
induction ls; simpl in *; intuition.
subst.
destruct (in_dec _ a0 (getUnique ls _)); simpl; auto.
destruct (in_dec _ a (getUnique ls _)); simpl.
eapply IHls. trivial.
right.
eapply IHls.
trivial.
Qed.
induction ls; intuition; simpl in *.
econstructor.
destruct (in_dec _ a (getUnique ls _)); eauto.
econstructor; eauto.
Qed.
induction ls; intuition; simpl in *.
destruct (in_dec eqd a (getUnique ls eqd)).
destruct ls; simpl in *; intuition.
simpl.
omega.
Qed.
Definition maxList(ls : list nat) : nat :=
fold_left max ls O.
induction ls; intuition; simpl in *.
eapply le_trans.
eapply Max.max_lub_l.
eapply le_refl.
eapply IHls.
Qed.
induction ls; intuition.
inversion H.
simpl in *.
intuition; subst.
eapply le_trans.
eapply Max.max_lub_r.
eapply le_refl.
eapply fold_left_max_ge_init.
Qed.
intuition.
eapply maxList_correct_h.
trivial.
Qed.
(* relational folds and other llist operations *)
Inductive pred_count(A : Type)(p : A -> Prop) : list A -> nat -> Prop :=
| pc_nil :
pred_count p nil 0
| pc_yes :
forall ls n a,
pred_count p ls n ->
p a ->
pred_count p (a :: ls) (S n)
| pc_no : forall ls n a,
pred_count p ls n ->
~p a ->
pred_count p (a :: ls) n.
induction ls; intuition; simpl in *.
inversion H; subst.
trivial.
inversion H; clear H; subst.
eapply le_n_S.
eapply IHls.
trivial.
econstructor.
eapply IHls.
trivial.
Qed.
(* listRepeat is used to show some interesting properties of rel_map and pred_count. *)
Fixpoint listRepeat(A : Type)(a : A) n :=
match n with
| 0 => nil
| S n' => a :: (listRepeat a n')
end.
induction n; intuition; simpl in *.
f_equal.
eauto.
Qed.
induction n; intuition; simpl in *.
inversion H. trivial.
inversion H; clear H; subst.
f_equal.
eapply IHn; eauto.
congruence.
Qed.
induction n; intuition; simpl in *.
inversion H0. trivial.
inversion H0; clear H0; subst.
intuition.
eapply IHn; eauto.
Qed.
induction ls; intuition.
inversion H. inversion H0. trivial.
inversion H; clear H; subst.
inversion H0; clear H0; subst.
f_equal.
eapply IHls; eauto.
intuition.
inversion H0; clear H0; subst.
intuition.
eapply IHls; eauto.
Qed.
induction 1; intuition; simpl in *.
f_equal.
eauto.
specialize (H1 a).
intuition.
Qed.
induction 1; intuition; simpl in *.
exists O. exists O.
intuition;
destruct n; simpl; econstructor.
destruct n0; simpl.
destruct (IHpred_count O).
destruct H1.
intuition. subst.
exists x.
exists (S x0).
intuition.
econstructor; trivial.
destruct (IHpred_count n0).
destruct H1.
destruct H1.
intuition. subst.
exists (S x).
exists x0.
intuition.
econstructor; trivial.
destruct n0; simpl.
destruct (IHpred_count O).
destruct H1.
intuition. subst.
exists x.
exists x0.
intuition.
econstructor; trivial.
destruct (IHpred_count n0).
destruct H1.
destruct H1.
intuition. subst.
exists x.
exists x0.
intuition.
econstructor; trivial.
Qed.
induction ls; intuition; simpl in *; subst.
econstructor.
econstructor; eauto.
Qed.
induction ls; intuition; simpl in *.
econstructor.
econstructor; eauto.
Qed.
induction n; intuition; simpl in *.
intuition.
intuition.
Qed.
induction ls1; intuition; simpl in *.
inversion H; subst; clear H.
simpl.
trivial.
inversion H; clear H; subst.
simpl.
econstructor; eauto.
econstructor; eauto.
Qed.
induction 1; intuition.
inversion H0; clear H0; subst.
econstructor; eauto.
econstructor; eauto.
inversion H; clear H; subst.
inversion H2; clear H2; subst.
econstructor; eauto.
econstructor; eauto.
eapply pc_no; eauto.
econstructor; eauto.
inversion H2; clear H2; subst.
econstructor; eauto.
econstructor; eauto.
econstructor; eauto.
econstructor; eauto.
Qed.
induction 1; intuition; simpl in *.
exfalso.
eapply H1.
eauto.
trivial.
eapply IHpred_count.
intuition.
eapply H1; eauto.
Qed.
intuition.
assert (pred_count P (a :: (removeFirst eqd ls a)) c).
eapply pred_count_permutation.
eapply removeFirst_permutation.
trivial.
trivial.
inversion H4; clear H4; subst.
assert (n = 0)%nat.
eapply pred_count_eq_none_inv.
eauto.
intuition.
eapply H3.
eapply removeFirst_in_iff.
eauto.
assert (~In a (removeFirst eqd ls a)).
eapply removeFirst_NoDup_not_in.
trivial.
intuition; subst; intuition.
trivial.
omega.
intuition.
Qed.
induction ls; intuition.
exists O.
econstructor.
destruct H0.
destruct (H a).
exists (S x).
econstructor; eauto.
exists x.
econstructor; eauto.
Qed.
Inductive rel_map(A B : Type)(r : A -> B -> Prop) : list A -> list B -> Prop :=
| rm_nil :
rel_map r nil nil
| rm_step :
forall lsa lsb a b,
rel_map r lsa lsb ->
r a b ->
rel_map r (a :: lsa) (b :: lsb).

Theorem rel_map_map2 : forall (A B C D : Type)(ls_c : list C)(ls_d: list D)(P : A -> B -> Prop)(f1 : C -> A)(f2 : D -> B),
rel_map (fun a b => P (f1 a) (f2 b)) ls_c ls_d ->
rel_map P (map f1 ls_c) (map f2 ls_d).