(* Contribution to the Coq Library   V6.3 (July 1999)                    *)
(***************************************************************************)
(* File: applications.v                                                    *)
(* auteur: alex@sysal.ibp.fr                                               *)
(* date: 19/10/95                                                          *)
(***************************************************************************)
Require Export couples.
(***************************************************************************)
(***************************************************************************)
(* Relations n-aires                                                       *)
(***************************************************************************)
(***************************************************************************)
Definition n_aire (n : nat) (a : E) (F : E -> Prop) :=
subset F (cart_power n a).
(* Pas de reciproque (dixit pagano pb des ensembles non decidables)        *)
(* Proof of lem_subset                                                     *)
intros; elim (axs_comprehension F b y); intros.
generalize H1; rewrite <- H; clear H H1 H2; intros.
elim H1; intros; auto with zfc.
Qed.
(* End of proof of lem_subset                                              *)
(***************************************************************************)
(***************************************************************************)
(* applications                                                            *)
(***************************************************************************)
(***************************************************************************)
Definition fun_ (f : E) :=
(exists a : E, (exists b : E, inc f (cartesien a b))) /\
(forall x y z : E, In (couple x y) f -> In (couple x z) f -> y = z).
(***************************************************************************)
(* Domaine d'une application                                               *)
(***************************************************************************)
Definition dom (f : E) :=
subset (fun v0 : E => fun_ f -> exists v1 : E, In (couple v0 v1) f)
(reunion (reunion f)).
(***************************************************************************)
(* Image d'une application                                                 *)
(***************************************************************************)
Definition Img (f : E) :=
subset (fun v1 : E => fun_ f -> exists v0 : E, In (couple v0 v1) f)
(reunion (reunion f)).
(***************************************************************************)
(* f est une application de a vers b                                       *)
(***************************************************************************)
Definition fun_sig (f a b : E) := fun_ f /\ dom f = a /\ inc (Img f) b.
(* Proof of lem_fun_sig_is_fun                                             *)
unfold fun_sig in |- *; intros.
elim H; clear H; intros; auto with zfc.
Qed.
(* End of proof of lem_fun_sig_is_fun                                      *)
(* Proof of lem_fun_sig_dom                                                *)
intros; elim H; clear H; intros; elim H0; clear H0; intros; auto with zfc.
Qed.
(* End of proof of lem_fun_sig_dom                                         *)
(* Proof of lem_fun_sig_img                                                *)
intros; elim H; clear H; intros; elim H0; clear H0; intros; auto with zfc.
Qed.
(* End of proof of lem_fun_sig_img                                         *)
(***************************************************************************)
(* f est une application surjective de a vers b                            *)
(***************************************************************************)
Definition fun_surj (f a b : E) := fun_ f /\ dom f = a /\ Img f = b.
(***************************************************************************)
(* f est une application injective                                         *)
(***************************************************************************)
Definition fun_inj (f a b : E) :=
fun_ f /\
dom f = a /\
inc (Img f) b /\
(forall b : E, In b (Img f) -> exUniq _ (fun a : E => In (couple a b) f)).
(***************************************************************************)
(* f est une bijection                                                     *)
(***************************************************************************)
Definition fun_bij (f a b : E) :=
fun_ f /\
dom f = a /\
Img f = b /\
(forall b : E, In b (Img f) -> exUniq _ (fun a : E => In (couple a b) f)).
(* Proof of lem_surj_to_sig                                                *)
unfold fun_surj in |- *; unfold fun_sig in |- *; intros.
elim H; clear H; intros; elim H0; clear H0; intros.
split;
[ auto with zfc
| split; [ auto with zfc | unfold inc in |- *; intros ] ].
generalize H2; rewrite H1; tauto.
Qed.
(* End of proof of lem_surj_to_sig                                         *)
(* Proof of lem_inj_to_sig                                                 *)
unfold fun_inj in |- *; unfold fun_sig in |- *; intros.
elim H; clear H; intros; elim H0; clear H0; intros; elim H1; clear H1; intros.
split; [ auto with zfc | split; auto with zfc ].
Qed.
(* End of proof of lem_inj_to_sig                                          *)
(* Proof of lem_bij_to_sig                                                 *)
unfold fun_bij in |- *; unfold fun_sig in |- *; intros.
elim H; clear H; intros; elim H0; clear H0; intros; elim H1; clear H1; intros.
split;
[ auto with zfc
| split; [ auto with zfc | unfold inc in |- *; intros ] ].
rewrite <- H1; auto with zfc.
Qed.
(* End of proof of lem_bij_to_sig                                          *)
(* Proof of lem_bij_is_inj                                                 *)
unfold fun_bij, fun_inj in |- *; intros.
elim H; clear H; intros; elim H0; clear H0; intros; elim H1; clear H1; intros.
split;
[ auto with zfc
| split;
[ auto with zfc
| split;
[ unfold inc in |- *; intros; rewrite <- H1; auto with zfc
| auto with zfc ] ] ].
Qed.
(* End of proof of lem_bij_is_inj                                          *)
(* Proof of lem_bij_is_inj                                                 *)
unfold fun_bij, fun_surj in |- *; intros.
elim H; clear H; intros; elim H0; clear H0; intros; elim H1; clear H1; intros.
split; [ auto with zfc | split; auto with zfc ].
Qed.
(* End of proof of lem_bij_is_inj                                          *)
(* Proof of lem_inj_surj_is_bij                                            *)
unfold fun_surj, fun_inj, fun_bij in |- *; intros.
elim H; clear H; intros; clear H; elim H1; clear H1; intros; clear H.
elim H0; clear H0; intros; elim H0; clear H0; intros; elim H2; clear H2;
intros.
split;
[ auto with zfc
| split; [ auto with zfc | split; auto with zfc ] ].
Qed.
(* End of proof of lem_inj_surj_is_bij                                     *)
(***************************************************************************)
(***************************************************************************)
(* L'application Vide                                                      *)
(***************************************************************************)
(***************************************************************************)
(* Proof of lem_vide_application                                           *)
unfold fun_ in |- *; split;
[ exists Vide; exists Vide; exact (lem_vide_is_inc (cartesien Vide Vide))
| intros ].
unfold Vide in H; elim (lem_vide_propertie (couple x y) var_vide);
auto with zfc.
Qed.
(* End of proof of lem_vide_application                                    *)
(* Proof of lem_dom_vide                                                   *)
apply axs_extensionnalite; intros; unfold iff in |- *; split; intros;
unfold dom in H.
elim
(axs_comprehension
(fun v0 : E => fun_ Vide -> exists v1 : E, In (couple v0 v1) Vide)
(reunion (reunion Vide)) v2); intros; generalize (H0 H);
clear H H0 H1; intros.
generalize H; rewrite lem_reunion_vide; rewrite lem_reunion_vide; tauto.
elim (lem_vide_propertie v2 var_vide); auto with zfc.
Qed.
(* End of proof of  lem_dom_vide                                           *)
(* Proof of lem_img_vide                                                   *)
apply axs_extensionnalite; intros; unfold iff in |- *; split; intros;
unfold Img in H.
elim
(axs_comprehension
(fun v1 : E => fun_ Vide -> exists v0 : E, In (couple v0 v1) Vide)
(reunion (reunion Vide)) v2); intros; generalize (H0 H);
clear H H0 H1; intros.
elim H; clear H; intros.
generalize H; rewrite lem_reunion_vide; rewrite lem_reunion_vide; tauto.
unfold Vide in H; elim (lem_vide_propertie v2 var_vide); auto with zfc.
Qed.
(* End of proof of lem_img_vide                                            *)
(* Proof of lem_fun_vide_sig                                               *)
unfold fun_sig in |- *; intros.
split;
[ exact lem_vide_application
| split;
[ exact lem_dom_vide | rewrite lem_img_vide; exact (lem_vide_is_inc a) ] ].
Qed.
(* End of proof of lem_fun_vide_sig                                        *)
(* Proof of lem_fun_and_dom                                                *)
intros; unfold dom in |- *.
elim
(axs_comprehension
(fun v0 : E => fun_ f -> exists v1 : E, In (couple v0 v1) f)
(reunion (reunion f)) a); intros; apply H2; clear H1 H2;
intros.
split; [ idtac | intros; exists b; auto with zfc ].
elim (axs_reunion (reunion f) a); intros; apply H2; clear H1 H2; intros.
exists (singleton a); split; [ idtac | exact (lem_x_in_sing_x a) ].
elim (axs_reunion f (singleton a)); intros; apply H2; clear H1 H2; intros.
exists (couple a b); split;
[ auto with zfc
| unfold couple in |- *;
elim (axs_paire (singleton a) (paire a b) (singleton a));
intros; apply H2; left; reflexivity ].
Qed.
(* End of proof of lem_fun_and_dom                                         *)
(* Proof of lem_fun_and_img                                                *)
intros; unfold Img in |- *.
elim
(axs_comprehension
(fun v1 : E => fun_ f -> exists v0 : E, In (couple v0 v1) f)
(reunion (reunion f)) b); intros; apply H2; clear H1 H2;
intros.
split; [ idtac | intros; exists a; auto with zfc ].
elim (axs_reunion (reunion f) b); intros; apply H2; clear H1 H2; intros;
exists (paire a b).
split;
[ idtac | elim (axs_paire a b b); intros; apply H2; right; reflexivity ].
elim (axs_reunion f (paire a b)); intros; apply H2; clear H1 H2; intros.
exists (couple a b); split;
[ auto with zfc
| unfold couple in |- *;
elim (axs_paire (singleton a) (paire a b) (paire a b));
intros; apply H2; right; reflexivity ].
Qed.
(* End of proof of lem_fun_and_img                                         *)
(* Proof of lem_App                                                   *)
intros; unfold dom in H0.
elim
(axs_comprehension
(fun v0 : E => fun_ f -> exists v1 : E, In (couple v0 v1) f)
(reunion (reunion f)) x); intros; generalize (H1 H0);
clear H0 H1 H2; intros.
elim H0; clear H0; intros; generalize (H1 H); clear H1; intros.
elim H1; clear H1; intros.
exists x0; split; [ exact (lem_fun_and_img f x x0 H H1) | auto with zfc ].
Qed.
(* End of proof of lem_App                                            *)
(* Proof of lem_App_rev                                               *)
intros; unfold Img in H0.
elim
(axs_comprehension
(fun v1 : E => fun_ f -> exists v0 : E, In (couple v0 v1) f)
(reunion (reunion f)) y); intros; generalize (H1 H0);
clear H0 H1 H2; intros.
elim H0; clear H0; intros; generalize (H1 H); clear H1; intros; elim H1;
clear H1; intros.
exists x; split; [ exact (lem_fun_and_dom f x y H H1) | auto with zfc ].
Qed.
(* End of proof of lem_App_rev                                        *)
(***************************************************************************)
(***************************************************************************)
(* Composition d'application                                               *)
(***************************************************************************)
(***************************************************************************)
Definition comp (f g a b c : E) (Af : fun_sig f a b)
(Ag : fun_sig g b c) :=
subset
(fun c : E =>
exists y : E, In (couple (first c) y) f /\ In (couple y (second c)) g)
(cartesien a c).
(***************************************************************************)
(* Il peut paraitre necessaire de reformuler la definition de la           *)
(* composition.                                                            *)
(***************************************************************************)
Definition comp2 (f g a b c : E) :=
subset
(fun x : E =>
fun_sig f a b ->
fun_sig g b c ->
exists y : E, In (couple (first x) y) f /\ In (couple y (second x)) g)
(cartesien a c).

Lemma lem_comp2_eq_comp :
forall (f g a b c : E) (Af : fun_sig f a b) (Ag : fun_sig g b c),
comp f g a b c Af Ag = comp2 f g a b c.