From 9f5c228d068d5da86db5fb1532ea3ca1b9c11c41 Mon Sep 17 00:00:00 2001 From: itamar Date: Mon, 9 Mar 2026 22:39:37 +0200 Subject: push push --- abgroup.v | 719 +++++++++++++++++++++++++++++++++++++++++++++++++++++ five.v | 128 ++++++++++ four.v | 188 ++++++++++++++ snake.v | 836 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1871 insertions(+) create mode 100644 abgroup.v create mode 100644 five.v create mode 100644 four.v create mode 100644 snake.v diff --git a/abgroup.v b/abgroup.v new file mode 100644 index 0000000..8825e33 --- /dev/null +++ b/abgroup.v @@ -0,0 +1,719 @@ +(* Abelian groups and Homomorphisms *) + +Require Import Utf8. +Require Import Setoid Morphisms. + +Reserved Notation "x '∈' S" (at level 60). +Reserved Notation "x '≡' y" (at level 70). + +(* Abelian Groups. + + Notes: + + -sets in groups are predicates (naive theory of sets); a value of type + gr_set is not necessarily in the group set. To be in the group set, it + must satisfy the predicate gr_mem, which is later syntaxified by the + usual symbol ∈. This allows to create subgroups by changing gr_mem. + + -group sets are setoids: there is a specific equality (gr_eq) which is + compatible with membership (gr_mem_compat), addition (gr_add_compat), + and opposite (gr_opp_compat). This allows to define quotient groups, + for example in cokernets, by changing this equality. +*) + +Record AbGroup := + { (* data *) + gr_set : Type; + gr_mem : gr_set → Prop where "x ∈ G" := (gr_mem x); + gr_eq : gr_set → gr_set → Prop where "x ≡ y" := (gr_eq x y); + gr_zero : gr_set where "0" := (gr_zero); + gr_add : gr_set → gr_set → gr_set where "x + y" := (gr_add x y); + gr_opp : gr_set → gr_set where "- x" := (gr_opp x); + (* properties *) + gr_zero_mem : 0 ∈ G; + gr_add_mem : ∀ x y, x ∈ G → y ∈ G → x + y ∈ G; + gr_add_0_l : ∀ x, 0 + x ≡ x; + gr_add_assoc : ∀ x y z, (x + y) + z ≡ x + (y + z); + gr_opp_mem : ∀ x, x ∈ G → - x ∈ G; + gr_add_opp_r : ∀ x, x + (- x) ≡ 0; + gr_add_comm : ∀ x y, x + y ≡ y + x; + gr_equiv : Equivalence gr_eq; + gr_mem_compat : ∀ x y, x ≡ y → x ∈ G → y ∈ G; + gr_add_compat : ∀ x y x' y', x ≡ y → x' ≡ y' → x + x' ≡ y + y'; + gr_opp_compat : ∀ x y, x ≡ y → - x ≡ - y }. + +(* coq stuff: implicit and renamed arguments *) + +Arguments gr_eq [_]. +Arguments gr_zero [_]. +Arguments gr_add [_]. +Arguments gr_opp [_]. +Arguments gr_zero_mem G : rename. +Arguments gr_add_mem G : rename. +Arguments gr_add_0_l G : rename. +Arguments gr_add_assoc G : rename. +Arguments gr_opp_mem G : rename. +Arguments gr_add_opp_r G : rename. +Arguments gr_add_comm G : rename. +Arguments gr_equiv G : rename. +Arguments gr_mem_compat G : rename. +Arguments gr_add_compat G : rename. +Arguments gr_opp_compat G : rename. + +(* syntaxes for expressions for groups elements and sets *) + +Delimit Scope group_scope with G. + +Notation "0" := (gr_zero) : group_scope. +Notation "a = b" := (gr_eq a b) : group_scope. +Notation "a ≠ b" := (¬ gr_eq a b) : group_scope. +Notation "a + b" := (gr_add a b) : group_scope. +Notation "a - b" := (gr_add a (gr_opp b)) : group_scope. +Notation "- a" := (gr_opp a) : group_scope. + +Notation "x '∈' S" := (gr_mem S x) (at level 60). +Notation "x '∉' S" := (¬ gr_mem S x) (at level 60). + +Open Scope group_scope. + +(* Homomorphism between groups *) + +Record HomGr (A B : AbGroup) := + { Happ : gr_set A → gr_set B; + Hmem_compat : ∀ x, x ∈ A → Happ x ∈ B; + Happ_compat : ∀ x y, x ∈ A → (x = y)%G → (Happ x = Happ y)%G; + Hadditive : ∀ x y, + x ∈ A → y ∈ A → (Happ (x + y) = Happ x + Happ y)%G }. + +(* coq stuff: implicit and renamed arguments *) + +Arguments Happ [A] [B]. +Arguments Hmem_compat _ _ f : rename. +Arguments Happ_compat _ _ f : rename. +Arguments Hadditive _ _ f : rename. + +(* Equality (gr_eq) of groups elements is an equivalence relation *) + +Instance gr_eq_rel {G} : Equivalence (@gr_eq G). +Proof. apply gr_equiv. Qed. + +(* Coq "Morphisms": they allow to use "rewrite" in expressions containing + opposites (-), additions (+) and memberships (∈) *) + +Instance gr_opp_morph {G} : Proper (@gr_eq G ==> @gr_eq G) (@gr_opp G). +Proof. +intros x y Hxy. +now apply gr_opp_compat. +Qed. + +Instance gr_add_morph {G} : + Proper (@gr_eq G ==> @gr_eq G ==> @gr_eq G) (@gr_add G). +Proof. +intros x y Hxy x' y' Hxy'. +now apply gr_add_compat. +Qed. + +Instance gr_mem_morph {G} : Proper (@gr_eq G ==> iff) (@gr_mem G). +Proof. +intros x y Hxy. +split; intros H. +-eapply gr_mem_compat; [ apply Hxy | easy ]. +-eapply gr_mem_compat; [ symmetry; apply Hxy | easy ]. +Qed. + +(* +Instance gr_app_morph {G H f} : Proper (@gr_eq G ==> @gr_eq H) (Happ f). +Proof. +intros x y Hxy. +apply Happ_compat; [ | easy ]. +... +blocked: we have to prove x ∈ G but it is not possible to +have this hypothesis in Proper +*) + +(* Miscellaneous theorems in groups *) + +Theorem gr_add_0_r : ∀ G (x : gr_set G), (x + 0 = x)%G. +Proof. +intros. +rewrite gr_add_comm. +apply gr_add_0_l. +Qed. + +Theorem gr_add_opp_l : ∀ G (x : gr_set G), (- x + x = 0)%G. +Proof. +intros. +rewrite gr_add_comm. +apply gr_add_opp_r. +Qed. + +Theorem gr_opp_zero : ∀ G, (- 0 = @gr_zero G)%G. +Proof. +intros. +rewrite <- gr_add_0_l. +apply gr_add_opp_r. +Qed. + +Theorem gr_sub_0_r : ∀ G (x : gr_set G), (x - 0 = x)%G. +Proof. +intros. +symmetry; rewrite <- gr_add_0_r at 1. +apply gr_add_compat; [ easy | now rewrite gr_opp_zero ]. +Qed. + +Theorem gr_sub_move_r : ∀ G (x y z : gr_set G), + (x - y = z)%G ↔ (x = z + y)%G. +Proof. +intros. +split; intros Hxyz. +-now rewrite <- Hxyz, gr_add_assoc, gr_add_opp_l, gr_add_0_r. +-now rewrite Hxyz, gr_add_assoc, gr_add_opp_r, gr_add_0_r. +Qed. + +Theorem gr_sub_move_l : ∀ G (x y z : gr_set G), + (x - y = z)%G ↔ (x = y + z)%G. +Proof. +intros. +split; intros Hxyz. +-now rewrite <- Hxyz, gr_add_comm, gr_add_assoc, gr_add_opp_l, gr_add_0_r. +-now rewrite Hxyz, gr_add_comm, <- gr_add_assoc, gr_add_opp_l, gr_add_0_l. +Qed. + +Theorem gr_opp_add_distr : ∀ G (x y : gr_set G), (- (x + y) = - x - y)%G. +Proof. +intros *. +symmetry. +apply gr_sub_move_r. +rewrite <- gr_add_0_l. +apply gr_sub_move_r. +symmetry; rewrite gr_add_assoc. +symmetry. +apply gr_sub_move_r. +rewrite gr_add_0_l. +apply gr_opp_compat, gr_add_comm. +Qed. + +Theorem gr_opp_involutive : ∀ G (x : gr_set G), (- - x = x)%G. +Proof. +intros. +transitivity (- - x + (- x + x))%G. +-rewrite <- gr_add_0_r at 1. + apply gr_add_compat; [ easy | ]. + now rewrite gr_add_opp_l. +-now rewrite <- gr_add_assoc, gr_add_opp_l, gr_add_0_l. +Qed. + +Theorem gr_eq_opp_l : ∀ G (x y : gr_set G), (- x = y)%G ↔ (x = - y)%G. +Proof. +intros. +split; intros Hxy. +-rewrite <- Hxy; symmetry; apply gr_opp_involutive. +-rewrite Hxy; apply gr_opp_involutive. +Qed. + +(* Theorems on homomorphisms *) + +Theorem Hzero : ∀ A B (f : HomGr A B), (Happ f 0 = 0)%G. +Proof. +intros. +assert (H1 : (@gr_zero A + 0 = 0)%G) by apply A. +assert (H2 : (Happ f 0 + Happ f 0 = Happ f 0)%G). { + rewrite <- Hadditive; [ | apply A | apply A ]. + apply f; [ apply A; apply A | apply A ]. +} +assert (H3 : (Happ f 0 + Happ f 0 - Happ f 0 = Happ f 0 - Happ f 0)%G). { + apply gr_add_compat; [ apply H2 | easy ]. +} +assert (H4 : (Happ f 0 + Happ f 0 - Happ f 0 = 0)%G). { + rewrite H3; apply gr_add_opp_r. +} +rewrite <- H4. +now rewrite gr_add_assoc, gr_add_opp_r, gr_add_0_r. +Qed. + +Theorem Hopp : ∀ A B (f : HomGr A B) x, + x ∈ A → (Happ f (- x) = - Happ f x)%G. +Proof. +intros * Hx. +assert (H2 : (Happ f (x - x) = Happ f 0)%G). { + apply Happ_compat; [ now apply A, A | apply A ]. +} +assert (H3 : (Happ f x + Happ f (- x) = Happ f 0)%G). { + rewrite <- H2. + symmetry; apply Hadditive; [ easy | now apply A ]. +} +assert (H4 : (Happ f x + Happ f (- x) = 0)%G). { + rewrite H3; apply Hzero. +} +symmetry; rewrite <- gr_add_0_l. +apply gr_sub_move_l. +now symmetry. +Qed. + +(* Images *) + +Theorem Im_zero_mem {G H} : ∀ (f : HomGr G H), + ∃ a : gr_set G, a ∈ G ∧ (Happ f a = 0)%G. +Proof. +intros. +exists 0%G. +split; [ apply gr_zero_mem | apply Hzero ]. +Qed. + +Theorem Im_add_mem {G H} : ∀ f (x y : gr_set H), + (∃ a : gr_set G, a ∈ G ∧ (Happ f a = x)%G) + → (∃ a : gr_set G, a ∈ G ∧ (Happ f a = y)%G) + → ∃ a : gr_set G, a ∈ G ∧ (Happ f a = x + y)%G. +Proof. +intros f y y' (x & Hxg & Hx) (x' & Hx'g & Hx'). +exists (gr_add x x'). +split; [ now apply G | ]. +rewrite Hadditive; [ | easy | easy ]. +now apply gr_add_compat. +Qed. + +Theorem Im_opp_mem {G H} : ∀ (f : HomGr G H) (x : gr_set H), + (∃ a : gr_set G, a ∈ G ∧ (Happ f a = x)%G) + → ∃ a : gr_set G, a ∈ G ∧ (Happ f a = - x)%G. +Proof. +intros f x (y & Hy & Hyx). +exists (gr_opp y). +split; [ now apply gr_opp_mem | ]. +rewrite <- Hyx. +now apply Hopp. +Qed. + +Theorem Im_mem_compat {G H} : ∀ f (x y : gr_set H), + (x = y)%G + → (∃ a, a ∈ G ∧ (Happ f a = x)%G) + → ∃ a, a ∈ G ∧ (Happ f a = y)%G. +intros * Hxy (z & Hz & Hfz). +exists z. +split; [ easy | now rewrite Hfz ]. +Qed. + +Definition Im {G H : AbGroup} (f : HomGr G H) := + {| gr_set := gr_set H; + gr_zero := gr_zero; + gr_eq := @gr_eq H; + gr_mem := λ b, ∃ a, a ∈ G ∧ (Happ f a = b)%G; + gr_add := @gr_add H; + gr_opp := @gr_opp H; + gr_zero_mem := Im_zero_mem f; + gr_add_mem := Im_add_mem f; + gr_add_0_l := gr_add_0_l H; + gr_add_assoc := gr_add_assoc H; + gr_opp_mem := Im_opp_mem f; + gr_add_opp_r := gr_add_opp_r H; + gr_add_comm := gr_add_comm H; + gr_equiv := gr_equiv H; + gr_mem_compat := Im_mem_compat f; + gr_add_compat := gr_add_compat H; + gr_opp_compat := gr_opp_compat H |}. + +(* Kernels *) + +Theorem Ker_zero_mem {G H} : ∀ (f : HomGr G H), 0%G ∈ G ∧ (Happ f 0 = 0)%G. +Proof. +intros f. +split; [ apply gr_zero_mem | apply Hzero ]. +Qed. + +Theorem Ker_add_mem {G H} : ∀ (f : HomGr G H) (x y : gr_set G), + x ∈ G ∧ (Happ f x = 0)%G + → y ∈ G ∧ (Happ f y = 0)%G → (x + y)%G ∈ G ∧ (Happ f (x + y) = 0)%G. +Proof. +intros f x x' (Hx, Hfx) (Hx', Hfx'). +split; [ now apply gr_add_mem | ]. +rewrite Hadditive; [ | easy | easy ]. +rewrite Hfx, Hfx'. +apply gr_add_0_r. +Qed. + +Theorem Ker_opp_mem {G H} : ∀ (f : HomGr G H) (x : gr_set G), + x ∈ G ∧ (Happ f x = 0)%G → (- x)%G ∈ G ∧ (Happ f (- x) = 0)%G. +Proof. +intros f x (Hx & Hfx). +split; [ now apply gr_opp_mem | ]. +rewrite Hopp; [ | easy ]. +rewrite Hfx. +apply gr_opp_zero. +Qed. + +Theorem Ker_mem_compat {G H} : ∀ (f : HomGr G H) x y, + (x = y)%G → x ∈ G ∧ (Happ f x = 0)%G → y ∈ G ∧ (Happ f y = 0)%G. +Proof. +intros * Hxy (ax, Hx). +split. +-eapply gr_mem_compat; [ apply Hxy | easy ]. +-rewrite <- Hx. + apply f; [ | easy ]. + now rewrite <- Hxy. +Qed. + +Definition Ker {G H : AbGroup} (f : HomGr G H) := + {| gr_set := gr_set G; + gr_zero := gr_zero; + gr_eq := @gr_eq G; + gr_mem := λ a, a ∈ G ∧ (Happ f a = gr_zero)%G; + gr_add := @gr_add G; + gr_opp := @gr_opp G; + gr_zero_mem := Ker_zero_mem f; + gr_add_mem := Ker_add_mem f; + gr_add_0_l := gr_add_0_l G; + gr_add_assoc := gr_add_assoc G; + gr_opp_mem := Ker_opp_mem f; + gr_add_opp_r := gr_add_opp_r G; + gr_add_comm := gr_add_comm G; + gr_equiv := gr_equiv G; + gr_mem_compat := Ker_mem_compat f; + gr_add_compat := gr_add_compat G; + gr_opp_compat := gr_opp_compat G |}. + +(* Cokernels + + x ∈ Coker f ↔ x ∈ H/Im f + quotient group is H with setoid, i.e. set with its own equality *) + +Definition Coker_eq {G H} (f : HomGr G H) x y := (x - y)%G ∈ Im f. + +Theorem Coker_add_0_l {G H} : ∀ (f : HomGr G H) x, Coker_eq f (0 + x)%G x. +Proof. +intros. +unfold Coker_eq. +exists 0%G. +split; [ apply gr_zero_mem | ]. +rewrite gr_add_0_l, gr_add_opp_r. +simpl; apply Hzero. +Qed. + +Theorem Coker_add_assoc {G H} : ∀ (f : HomGr G H) x y z, + Coker_eq f (x + y + z)%G (x + (y + z))%G. +Proof. +intros. +unfold Coker_eq. +exists 0%G. +split; [ apply gr_zero_mem | ]. +rewrite Hzero. +symmetry; simpl. +apply gr_sub_move_r. +rewrite gr_add_0_l. +apply gr_add_assoc. +Qed. + +Theorem Coker_add_opp_r {G H} : ∀ (f : HomGr G H) x, Coker_eq f (x - x)%G 0%G. +Proof. +intros. +exists 0%G. +split; [ apply gr_zero_mem | ]. +now rewrite Hzero, gr_add_opp_r, gr_sub_0_r. +Qed. + +Theorem Coker_add_comm {G H} : ∀ (f : HomGr G H) x y, + Coker_eq f (x + y)%G (y + x)%G. +Proof. +intros. +exists 0%G. +split; [ apply gr_zero_mem | ]. +rewrite Hzero. +symmetry. +simpl; apply gr_sub_move_l. +now rewrite gr_add_0_r, gr_add_comm. +Qed. + +Theorem Coker_eq_refl {G H} (f : HomGr G H) : Reflexive (Coker_eq f). +Proof. +intros x. +exists 0%G. +split; [ apply gr_zero_mem | ]. +rewrite gr_add_opp_r. +simpl; apply Hzero. +Qed. + +Theorem Coker_eq_symm {G H} (f : HomGr G H) : Symmetric (Coker_eq f). +Proof. +intros x y Hxy. +destruct Hxy as (z & Hz & Hfz). +exists (- z)%G. +split; [ now apply gr_opp_mem | ]. +rewrite Hopp; [ | easy ]. +rewrite Hfz. +simpl; rewrite gr_opp_add_distr, gr_add_comm. +apply gr_add_compat; [ | easy ]. +apply gr_opp_involutive. +Qed. + +Theorem Coker_eq_trans {G H} (f : HomGr G H) : Transitive (Coker_eq f). +Proof. +intros x y z Hxy Hyz. +simpl in Hxy, Hyz. +destruct Hxy as (t & Ht & Hft). +destruct Hyz as (u & Hu & Hfu). +exists (t + u)%G. +split; [ now apply gr_add_mem | ]. +rewrite Hadditive; [ | easy | easy ]. +rewrite Hft, Hfu. +simpl; rewrite gr_add_assoc. +apply gr_add_compat; [ easy | ]. +now rewrite <- gr_add_assoc, gr_add_opp_l, gr_add_0_l. +Qed. + +Theorem Coker_equiv {G H} : ∀ (f : HomGr G H), Equivalence (Coker_eq f). +Proof. +intros. +unfold Coker_eq; split. +-apply Coker_eq_refl. +-apply Coker_eq_symm. +-apply Coker_eq_trans. +Qed. + +Add Parametric Relation {G H} {f : HomGr G H} : (gr_set (Im f)) (Coker_eq f) + reflexivity proved by (Coker_eq_refl f) + symmetry proved by (Coker_eq_symm f) + transitivity proved by (Coker_eq_trans f) + as gr_cokereq_rel. + +Theorem Coker_mem_compat {G H} : ∀ (f : HomGr G H) x y, + Coker_eq f x y → x ∈ H → y ∈ H. +Proof. +intros * Heq Hx. +destruct Heq as (z & Hz & Hfz). +apply gr_mem_compat with (x := (x - Happ f z)%G). +-rewrite Hfz. + simpl; apply gr_sub_move_r. + now rewrite gr_add_comm, gr_add_assoc, gr_add_opp_l, gr_add_0_r. +-simpl; apply gr_add_mem; [ easy | ]. + apply gr_opp_mem. + now apply f. +Qed. + +Theorem Coker_add_compat {G H} : ∀ (f : HomGr G H) x y x' y', + Coker_eq f x y → Coker_eq f x' y' → Coker_eq f (x + x')%G (y + y')%G. +Proof. +intros f x y x' y' (z & Hz & Hfz) (z' & Hz' & Hfz'). +exists (z + z')%G. +split. +-now apply gr_add_mem. +-rewrite Hadditive; [ | easy | easy ]. + rewrite Hfz, Hfz'; simpl. + rewrite gr_add_assoc; symmetry. + rewrite gr_add_assoc; symmetry. + apply gr_add_compat; [ easy | ]. + rewrite gr_add_comm, gr_add_assoc. + apply gr_add_compat; [ easy | ]. + rewrite gr_add_comm; symmetry. + apply gr_opp_add_distr. +Qed. + +Theorem Coker_opp_compat {G H} :∀ (f : HomGr G H) x y, + Coker_eq f x y → Coker_eq f (- x)%G (- y)%G. +Proof. +intros * (z & Hz & Hfz). +unfold Coker_eq; simpl. +exists (- z)%G. +split; [ now apply gr_opp_mem | ]. +rewrite Hopp; [ | easy ]. +rewrite Hfz. +simpl; apply gr_opp_add_distr. +Qed. + +Definition Coker {G H : AbGroup} (f : HomGr G H) := + {| gr_set := gr_set H; + gr_zero := gr_zero; + gr_eq := Coker_eq f; + gr_mem := gr_mem H; + gr_add := @gr_add H; + gr_opp := @gr_opp H; + gr_zero_mem := @gr_zero_mem H; + gr_add_mem := @gr_add_mem H; + gr_add_0_l := Coker_add_0_l f; + gr_add_assoc := Coker_add_assoc f; + gr_opp_mem := gr_opp_mem H; + gr_add_opp_r := Coker_add_opp_r f; + gr_add_comm := Coker_add_comm f; + gr_equiv := Coker_equiv f; + gr_mem_compat := Coker_mem_compat f; + gr_add_compat := Coker_add_compat f; + gr_opp_compat := Coker_opp_compat f |}. + +(* Exact sequences *) + +Inductive sequence {A : AbGroup} := + | SeqEnd : sequence + | Seq : ∀ {B} (f : HomGr A B), @sequence B → sequence. + +Notation "A ⊂ B" := (∀ a, a ∈ A → a ∈ B) (at level 60). +Notation "A == B" := (A ⊂ B ∧ B ⊂ A) (at level 60). + +Fixpoint exact_sequence {A : AbGroup} (S : sequence) := + match S with + | SeqEnd => True + | Seq f S' => + match S' with + | SeqEnd => True + | Seq g S'' => Im f == Ker g ∧ exact_sequence S' + end + end. + +Delimit Scope seq_scope with S. + +Notation "[ ]" := SeqEnd (format "[ ]") : seq_scope. +Notation "[ x ]" := (Seq x SeqEnd) : seq_scope. +Notation "[ x ; y ; .. ; z ]" := (Seq x (Seq y .. (Seq z SeqEnd) ..)) : seq_scope. + +Arguments exact_sequence _ S%S. + +(* + f + A------>B + | | + g| |h + | | + v v + C------>D + k +*) + +Definition diagram_commutes {A B C D} + (f : HomGr A B) (g : HomGr A C) (h : HomGr B D) (k : HomGr C D) := + ∀ x, (Happ h (Happ f x) = Happ k (Happ g x))%G. + +(* The trivial group *) + +Theorem Gr1_add_0_l : ∀ x : True, I = x. +Proof. now destruct x. Qed. + +Definition Gr1 := + {| gr_set := True; + gr_mem _ := True; + gr_eq := eq; + gr_zero := I; + gr_add _ _ := I; + gr_opp x := x; + gr_zero_mem := I; + gr_add_mem _ _ _ _ := I; + gr_add_0_l := Gr1_add_0_l; + gr_add_assoc _ _ _ := eq_refl; + gr_opp_mem _ H := H; + gr_add_opp_r _ := eq_refl; + gr_add_comm _ _ := eq_refl; + gr_equiv := eq_equivalence; + gr_mem_compat _ _ _ _ := I; + gr_add_compat _ _ _ _ _ _ := eq_refl; + gr_opp_compat _ _ H := H |}. + +(* *) + +Definition is_mono {A B} (f : HomGr A B) := + ∀ C (g₁ g₂ : HomGr C A), + (∀ z, z ∈ C → (Happ f (Happ g₁ z) = Happ f (Happ g₂ z))%G) + → (∀ z, z ∈ C → (Happ g₁ z = Happ g₂ z)%G). + +Definition is_epi {A B} (f : HomGr A B) := + ∀ C (g₁ g₂ : HomGr B C), + (∀ x, x ∈ A → (Happ g₁ (Happ f x) = Happ g₂ (Happ f x))%G) + → (∀ y, y ∈ B → (Happ g₁ y = Happ g₂ y)%G). + +Definition is_iso {A B} (f : HomGr A B) := + ∃ g : HomGr B A, + (∀ x, x ∈ A → (Happ g (Happ f x) = x)%G) ∧ + (∀ y, y ∈ B → (Happ f (Happ g y) = y)%G). + +(* epimorphism is surjective and monomorphism is injective *) + +Theorem epi_is_surj : ∀ {A B} {f : HomGr A B}, + is_epi f + → ∀ y, y ∈ B → ∃ t, t ∈ A ∧ (Happ f t = y)%G. +Proof. +intros * Hed y Hy. +(* type gr_set B → gr_set (Coker f) *) +set (v y1 := let _ : gr_set B := y1 in y1 : gr_set (Coker f)). +assert (Hmc : ∀ y1, y1 ∈ B → v y1 ∈ B) by easy. +assert (Hac : ∀ y1 y2, y1 ∈ B → (y1 = y2)%G → (v y1 = v y2)%G). { + intros * Hy1 Hyy. + exists 0; split; [ apply A | ]. + now unfold v; simpl; rewrite Hzero, Hyy, gr_add_opp_r. +} +assert (Had : ∀ y1 y2, y1 ∈ B → y2 ∈ B → (v (y1 + y2) = v y1 + v y2)%G). { + intros * Hy1 Hy2. + exists 0; split; [ apply A | now unfold v; rewrite Hzero, gr_add_opp_r ]. +} +set (hv := + {| Happ := v; + Hmem_compat := Hmc; + Happ_compat := Hac; + Hadditive := Had |}). +assert (Hmc₀ : ∀ y1, y1 ∈ B → 0 ∈ Coker f) by (intros; apply B). +assert (Hac₀ : ∀ y1 y2, y1 ∈ B → (y1 = y2)%G → (@gr_zero (Coker f) = 0)%G). { + intros * Hy1 Hyy. + simpl; unfold Coker_eq; simpl. + exists 0; split; [ apply A | now rewrite Hzero, gr_add_opp_r ]. +} +assert (Had₀ : ∀ y1 y2, y1 ∈ B → y2 ∈ B → (@gr_zero (Coker f) = 0 + 0)%G). { + intros * Hy1 Hy2. + simpl; unfold Coker_eq; simpl. + exists 0; split; [ apply A | now rewrite Hzero, gr_add_0_r, gr_sub_0_r ]. +} +set (hw := + {| Happ _ := 0; + Hmem_compat := Hmc₀; + Happ_compat := Hac₀; + Hadditive := Had₀ |}). +specialize (Hed (Coker f) hv hw) as H1. +assert (H : ∀ x, x ∈ A → (Happ hv (Happ f x) = Happ hw (Happ f x))%G). { + intros x Hx. + simpl; unfold v; unfold Coker_eq; simpl. + exists x; split; [ easy | now rewrite gr_sub_0_r ]. +} +specialize (H1 H y Hy); clear H. +simpl in H1; unfold Coker_eq in H1; simpl in H1. +destruct H1 as (x & Hx). +rewrite gr_sub_0_r in Hx. +now exists x. +Qed. + +Theorem mono_is_inj : ∀ {A B} {f : HomGr A B}, + is_mono f + → ∀ x1 x2, x1 ∈ A → x2 ∈ A → (Happ f x1 = Happ f x2)%G → (x1 = x2)%G. +Proof. +intros * Hf * Hx1 Hx2 Hxx. +(* morphism identity from Ker f to A *) +set (v x := let _ : gr_set (Ker f) := x in x : gr_set A). +assert (Hmc : ∀ x, x ∈ Ker f → v x ∈ A) by (intros x Hx; apply Hx). +set (hv := + {| Happ := v; + Hmem_compat := Hmc; + Happ_compat _ _ _ H := H; + Hadditive _ _ _ _ := reflexivity _ |}). +(* morphism null from Ker f to A *) +set (hw := + {| Happ x := let _ : gr_set (Ker f) := x in 0 : gr_set A; + Hmem_compat _ _ := gr_zero_mem A; + Happ_compat _ _ _ _ := reflexivity _; + Hadditive _ _ _ _ := symmetry (gr_add_0_r _ _) |}). +specialize (Hf (Ker f) hv hw) as H1. +assert (H : ∀ z, z ∈ Ker f → (Happ f (Happ hv z) = Happ f (Happ hw z))%G). { + intros z (Hz, Hfz). + unfold hv, hw, v; simpl. + now rewrite Hfz, Hzero. +} +specialize (H1 H (x1 - x2)); clear H. +assert (H : x1 - x2 ∈ Ker f). { + split. + -apply A; [ easy | now apply A ]. + -rewrite Hadditive; [ | easy | now apply A ]. + rewrite Hopp; [ | easy ]. + now rewrite Hxx, gr_add_opp_r. +} +specialize (H1 H); clear H. +unfold hv, hw, v in H1; simpl in H1. +apply gr_sub_move_r in H1. +now rewrite gr_add_0_l in H1. +Qed. + +(* We sometimes need these axioms *) + +Definition Choice := ∀ {A B} {R : A → B → Prop}, + (∀ x : A, ∃ y : B, R x y) → ∃ f : A → B, ∀ x : A, R x (f x). +Definition Decidable_Membership := ∀ G x, {x ∈ G} + {x ∉ G}. + diff --git a/five.v b/five.v new file mode 100644 index 0000000..7bddcc5 --- /dev/null +++ b/five.v @@ -0,0 +1,128 @@ +(* Five lemma *) + +Require Import Utf8. +Require Import AbGroup Setoid. +Require Import four. + +Theorem is_iso_is_epi : ∀ A B (f : HomGr A B), is_iso f → is_epi f. +Proof. +intros * (g & Hgf & Hfg) C * Hgg * Hy. +specialize (Hfg y Hy) as H1. +etransitivity. +-apply g₁; [ easy | symmetry; apply H1 ]. +-rewrite Hgg; [ | now apply g ]. + apply g₂; [ now apply f, g | easy ]. +Qed. + +Theorem is_iso_is_mono : ∀ A B (f : HomGr A B), is_iso f → is_mono f. +Proof. +intros * (g & Hgf & Hfg) C * Hgg * Hz. +specialize (Hgg z Hz) as H1. +apply (Happ_compat _ _ g) in H1; [ | now apply f, g₁ ]. +rewrite Hgf in H1; [ | now apply g₁ ]. +rewrite Hgf in H1; [ | now apply g₂ ]. +easy. +Qed. + +Theorem epi_mono_is_iso : ∀ A B (f : HomGr A B), + Decidable_Membership * Choice + → is_epi f → is_mono f → is_iso f. +Proof. +intros * (mem_dec, choice) He Hm. +unfold is_iso. +specialize (epi_is_surj He) as H1. +specialize (mono_is_inj Hm) as H2. +assert (H3 : ∀ y, ∃ t, y ∈ B → t ∈ A ∧ (Happ f t = y)%G). { + intros y. + specialize (H1 y). + specialize (mem_dec B y) as [H3| H3]; [ | now exists 0 ]. + specialize (H1 H3) as (x & Hx & Hfx). + exists x; intros H; easy. +} +specialize (choice _ _ _ H3) as (g & Hg). +assert (Hmc : ∀ x : gr_set B, x ∈ B → g x ∈ A). { + intros y Hy. + now specialize (Hg _ Hy). +} +assert (Hac : ∀ x y, x ∈ B → (x = y)%G → (g x = g y)%G). { + intros y1 y2 Hy1 Hyy. + assert (Hy2 : y2 ∈ B) by now apply (gr_mem_compat _ y1). + specialize (Hg _ Hy1) as H; destruct H as (Hgy1, Hfgy1). + specialize (Hg _ Hy2) as H; destruct H as (Hgy2, Hfgy2). + move Hgy2 before Hgy1. + rewrite Hyy in Hfgy1 at 2. + rewrite <- Hfgy2 in Hfgy1. + now apply H2. +} +assert (Had : ∀ x y, x ∈ B → y ∈ B → (g (x + y) = g x + g y)%G). { + intros y1 y2 Hy1 Hy2. + specialize (Hg _ Hy1) as H; destruct H as (Hg1, Hfg1). + specialize (Hg _ Hy2) as H; destruct H as (Hg2, Hfg2). + move Hg2 before Hg1. + apply H2; [ now apply Hmc, B | now apply A | ]. + rewrite Hadditive; [ | easy | easy ]. + rewrite Hfg1, Hfg2. + now apply Hg, B. +} +set (hv := + {| Happ := g; + Hmem_compat := Hmc; + Happ_compat := Hac; + Hadditive := Had |}). +exists hv; simpl. +split. +-intros x Hx. + apply H2; [ now apply Hmc, f | easy | ]. + now apply Hg, f. +-intros y Hy. + now apply Hg. +Qed. + + + +Lemma five : + ∀ (A B C D E A' B' C' D' E' : AbGroup) + (f : HomGr A B) (g : HomGr B C) (h : HomGr C D) (j : HomGr D E) + (f' : HomGr A' B') (g' : HomGr B' C') + (h' : HomGr C' D') (j' : HomGr D' E') + (a : HomGr A A') (b : HomGr B B') (c : HomGr C C') + (d : HomGr D D') (e : HomGr E E'), + Decidable_Membership * Choice + → diagram_commutes f a b f' + → diagram_commutes g b c g' + → diagram_commutes h c d h' + → diagram_commutes j d e j' + → exact_sequence [f; g; h; j] + → exact_sequence [f'; g'; h'; j'] + → is_epi a ∧ is_iso b ∧ is_iso d ∧ is_mono e + → is_iso c. +Proof. +intros * dc. +intros Hcff' Hcgg' Hchh' Hcjj' s s' (Hea & Hib & Hid & Hme). +specialize (four_1 B C D E B' C' D' E') as H1. +specialize (H1 g h j g' h' j' b c d e). +specialize (H1 Hcgg' Hchh' Hcjj'). +assert (H : exact_sequence [g; h; j]) by apply s. +specialize (H1 H); clear H. +assert (H : exact_sequence [g'; h'; j']) by apply s'. +specialize (H1 H); clear H. +assert (H : is_epi b ∧ is_epi d ∧ is_mono e). { + split; [ | split ]; [ | | easy ]; now apply is_iso_is_epi. +} +specialize (H1 H); clear H. +specialize (four_2 A B C D A' B' C' D') as H2. +specialize (H2 f g h f' g' h' a b c d). +specialize (H2 Hcff' Hcgg' Hchh'). +assert (H : exact_sequence [f; g; h]) by now destruct s as (t & u & v). +specialize (H2 H); clear H. +assert (H : exact_sequence [f'; g'; h']) by now destruct s' as (t & u & v). +specialize (H2 H); clear H. +assert (H : is_mono b ∧ is_mono d ∧ is_epi a). { + split; [ | split ]; [ | | easy ]; now apply is_iso_is_mono. +} +specialize (H2 H); clear H. +now apply epi_mono_is_iso. +Qed. + +Check five. + diff --git a/four.v b/four.v new file mode 100644 index 0000000..c47bf16 --- /dev/null +++ b/four.v @@ -0,0 +1,188 @@ +Require Import Utf8. +Require Import AbGroup Setoid. + +(* + g h j + B------>C------>D------>E + | | | ∩ + b| c| d| e| + v | v | + v v v v + B'----->C'----->D'----->E' + g' h' j' + + If 1/ the diagram is commutative, + 2/ (g, h, j) and (g', h', j') are exact, + 3/ b and d are epimorphisms, + 4/ e is monomorphism, + Then + c is an epimorphism. +*) + +Lemma four_1 : + ∀ (B C D E B' C' D' E' : AbGroup) + (g : HomGr B C) (h : HomGr C D) (j : HomGr D E) + (g' : HomGr B' C') (h' : HomGr C' D') (j' : HomGr D' E') + (b : HomGr B B') (c : HomGr C C') + (d : HomGr D D') (e : HomGr E E'), + diagram_commutes g b c g' + → diagram_commutes h c d h' + → diagram_commutes j d e j' + → exact_sequence [g; h; j] + → exact_sequence [g'; h'; j'] + → is_epi b ∧ is_epi d ∧ is_mono e + → is_epi c. +Proof. +intros * Hcgg' Hchh' Hcjj' s s' (Heb & Hed & Hme). +unfold is_epi. +enough + (∀ T (g₁ g₂ : HomGr C' T), + (∀ z, z ∈ C → (Happ g₁ (Happ c z) = Happ g₂ (Happ c z))%G) + → ∀ z', z' ∈ C' → (Happ g₁ z' = Happ g₂ z')%G). { + now intros T g₁ g₂ H1; apply H. +} +intros * Hgc * Hz'. +assert (H : ∃ t, t ∈ D ∧ (Happ d t = Happ h' z')%G). { + apply epi_is_surj; [ easy | now apply h' ]. +} +destruct H as (t & Ht & Hdt). +move t after z'; move Ht after Hz'. +assert (H : ∃ z, z ∈ C ∧ (Happ h z = t)%G). { + assert (H : t ∈ Ker j). { + split; [ easy | ]. + assert (H : (Happ e (Happ j t) = 0)%G). { + rewrite Hcjj'. + + etransitivity; [ apply Happ_compat | ]; [ | apply Hdt | ]; cycle 1. + -assert (H : Happ h' z' ∈ Im h') by (exists z'; easy). + now apply s' in H; simpl in H. + -now apply d. + } + specialize (mono_is_inj Hme) as H1. + apply H1; [ now apply j | apply E | now rewrite Hzero ]. + } + apply s in H. + destruct H as (z & Hz & Hhz). + now exists z. +} +destruct H as (z & Hz & Hhz). +move z after t; move Hz after Ht. +assert (H : Happ c z - z' ∈ Ker h'). { + split. + -apply C'; [ now apply c | now apply C' ]. + -rewrite Hadditive; [ | now apply c | now apply C' ]. + rewrite Hopp; [ | easy ]. + rewrite <- Hchh'. + apply gr_sub_move_r. + rewrite gr_add_0_l. + etransitivity; [ apply Happ_compat | ]; [ | apply Hhz | ]; try easy. + now apply h. +} +apply s' in H. +destruct H as (y' & Hy' & Hgy'). +move y' after z'; move Hy' before Hz'. +assert (H : ∃ y, y ∈ B ∧ (Happ b y = y')%G) by now apply epi_is_surj. +destruct H as (y & Hy & Hby). +move y after z; move Hy before Hz. +specialize (Hgc (z - Happ g y)) as H1. +assert (H : z - Happ g y ∈ C). { + apply C; [ easy | now apply C, g ]. +} +specialize (H1 H); clear H. +assert (H : (Happ c (z - Happ g y) = z')%G). { + rewrite Hadditive; [ | easy | now apply C, g ]. + rewrite Hopp; [ | now apply g ]. + apply gr_sub_move_r. + apply gr_sub_move_l. + rewrite <- Hgy'. + rewrite Hcgg'. + apply g'; [ easy | now symmetry ]. +} +symmetry in H. +etransitivity; [ apply Happ_compat | ]; [ | apply H | ]; cycle 1. +-rewrite H1. + apply g₂; [ | easy ]. + apply c, C; [ easy | now apply C, g ]. +-easy. +Qed. + +(* + f g h + A------>B------>C------>D + | ∩ | ∩ + a| b| c| d| + v | | | + v v v v + A'----->B'----->C'----->D' + f' g' h' + + If 1/ the diagram is commutative, + 2/ (f, g, h) and (f', g', h') are exact, + 3/ b and d are monomorphisms, + 4/ a is epimorphism, + Then + c is an monomorphism. +*) + +Lemma four_2 : + ∀ (A B C D A' B' C' D' : AbGroup) + (f : HomGr A B) (g : HomGr B C) (h : HomGr C D) + (f' : HomGr A' B') (g' : HomGr B' C') (h' : HomGr C' D') + (a : HomGr A A') (b : HomGr B B') + (c : HomGr C C') (d : HomGr D D'), + diagram_commutes f a b f' + → diagram_commutes g b c g' + → diagram_commutes h c d h' + → exact_sequence [f; g; h] + → exact_sequence [f'; g'; h'] + → is_mono b ∧ is_mono d ∧ is_epi a + → is_mono c. +Proof. +intros * Hcff' Hcgg' Hchh' s s' (Hmb & Hmd & Hea). +intros T g₁ g₂ Hcg u Hu. +specialize (Hcg u Hu) as H. +assert (H1 :( Happ c (Happ g₁ u - Happ g₂ u) = 0)%G). { + rewrite Hadditive; [ | now apply g₁ | now apply C, g₂ ]. + rewrite Hopp; [ | now apply g₂ ]. + now rewrite H, gr_add_opp_r. +} +clear H. +symmetry; rewrite <- gr_add_0_r; symmetry. +apply gr_sub_move_l. +set (z := Happ g₁ u - Happ g₂ u) in H1 |-*. +assert (Hz : z ∈ C) by (apply C; [ now apply g₁ | now apply C, g₂ ]). +move Hz before z. +generalize H1; intros H2. +apply (Happ_compat _ _ h') in H2; [ | now apply c ]. +rewrite <- Hchh', Hzero in H2. +assert (H3 : z ∈ Ker h). { + split; [ easy | ]. + apply (mono_is_inj Hmd); [ now apply h | apply D | now rewrite Hzero ]. +} +apply s in H3. +destruct H3 as (y & Hy & Hgy). +generalize Hgy; intros H3. +apply (Happ_compat _ _ c) in H3; [ | now apply g ]. +rewrite Hcgg', H1 in H3. +assert (H4 : Happ b y ∈ Ker g') by (split; [ now apply b | easy ]). +apply s' in H4. +destruct H4 as (x' & Hx' & Hfx'). +assert (H : ∃ x, x ∈ A ∧ (Happ a x = x')%G) by now apply epi_is_surj. +destruct H as (x & Hx & Hax). +assert (H4 : (Happ f' (Happ a x) = Happ b y)%G). { + etransitivity; [ apply Happ_compat | ]; [ | apply Hax | ]; try easy. + now apply a. +} +rewrite <- Hcff' in H4. +apply mono_is_inj in H4; [ | easy | now apply f | easy ]. +assert (H5 : (Happ g (Happ f x) = z)%G). { + etransitivity; [ apply Happ_compat | ]; [ | apply H4 | ]; try easy. + now apply f. +} +rewrite <- H5. +assert (H : Happ f x ∈ Im f) by now exists x. +apply s in H. +now destruct H. +Qed. + + diff --git a/snake.v b/snake.v new file mode 100644 index 0000000..59c159e --- /dev/null +++ b/snake.v @@ -0,0 +1,836 @@ +(* Snake lemma *) + +Require Import Utf8. +Require Import Classes.RelationClasses. +Require Import Setoid. + +Require Import AbGroup. + +(* Functor HomGr A B → HomGr (KerA) (KerB) *) + +Theorem KK_mem_compat {A B A' B'} : ∀ (a : HomGr A A') (b : HomGr B B') f f', + diagram_commutes f a b f' + → ∀ x : gr_set (Ker a), x ∈ Ker a → Happ f x ∈ Ker b. +intros * Hc * (Hx & Hax). +split; [ now apply f | ]. +rewrite Hc, <- (Hzero _ _ f'). +apply f'; [ apply a, Hx | easy ]. +Qed. + +Theorem KK_app_compat {A B A'} : ∀ (f : HomGr A B) (a : HomGr A A'), + ∀ x y : gr_set (Ker a), x ∈ Ker a → (x = y)%G → (Happ f x = Happ f y)%G. +Proof. +intros * Hx Hxy. +simpl in Hx. +now apply f. +Qed. + +Theorem KK_additive {A B A'} : ∀ (f : HomGr A B) (a : HomGr A A'), + ∀ x y : gr_set (Ker a), + x ∈ Ker a → y ∈ Ker a → (Happ f (x + y) = Happ f x + Happ f y)%G. +Proof. +intros * Hx Hx'; simpl in Hx, Hx'. +now apply f. +Qed. + +Definition HomGr_Ker_Ker {A B A' B'} + {f : HomGr A B} {f' : HomGr A' B'} (a : HomGr A A') (b : HomGr B B') + (Hc : diagram_commutes f a b f') := + {| Happ (x : gr_set (Ker a)) := Happ f x : gr_set (Ker b); + Hmem_compat := KK_mem_compat a b f f' Hc; + Happ_compat := KK_app_compat f a; + Hadditive := KK_additive f a |}. + +(* Functor f:HomGr A B → g:HomGr B C → HomGr (CoKer f) (Coker g) *) + +Theorem CC_mem_compat {A B A' B'} : + ∀ (f' : HomGr A' B') (a : HomGr A A') (b : HomGr B B'), + ∀ x : gr_set (Coker a), x ∈ Coker a → Happ f' x ∈ Coker b. +Proof. +intros * Hx. +now apply f'. +Qed. + +Theorem CC_app_compat {A B A' B'} : + ∀ (f : HomGr A B) (f' : HomGr A' B') (a : HomGr A A') (b : HomGr B B'), + diagram_commutes f a b f' + → ∀ x y : gr_set (Coker a), + x ∈ Coker a + → (x = y)%G + → @gr_eq (Coker b) (Happ f' x) (Happ f' y)%G. +Proof. +intros * Hc * Hx Hxy. +assert (Hy : y ∈ Coker a) by now apply (gr_mem_compat _ x). +simpl in Hx, x, y, Hxy; simpl. +destruct Hxy as (z & Hz & Haz). +simpl; unfold Coker_eq; simpl. +exists (Happ f z). +split; [ now apply f | ]. +rewrite Hc. +transitivity (Happ f' (x - y)%G). +-apply Happ_compat; [ now apply a | easy ]. +-rewrite Hadditive; [ | easy | ]. + +apply gr_add_compat; [ easy | now apply Hopp ]. + +now apply A'. +Qed. + +Theorem CC_additive {A B A' B'} : + ∀ (f' : HomGr A' B') (a : HomGr A A') (b : HomGr B B'), + ∀ x y : gr_set (Coker a), + x ∈ Coker a + → y ∈ Coker a + → @gr_eq (Coker b) (Happ f' (x + y))%G (Happ f' x + Happ f' y)%G. +Proof. +intros * Hx Hy; simpl in Hx, Hy. +exists 0%G. +split; [ apply B | ]. +rewrite Hzero; symmetry. +simpl; apply gr_sub_move_r. +rewrite gr_add_0_l. +now apply Hadditive. +Qed. + +Definition HomGr_Coker_Coker {A B A' B'} + {f : HomGr A B} {f' : HomGr A' B'} (a : HomGr A A') (b : HomGr B B') + (Hc : diagram_commutes f a b f') := + {| Happ (x : gr_set (Coker a)) := Happ f' x : gr_set (Coker b); + Hmem_compat := CC_mem_compat f' a b; + Happ_compat := CC_app_compat f f' a b Hc; + Hadditive := CC_additive f' a b |}. + +Theorem g_is_surj {B C C' g} (c : HomGr C C') {cz : HomGr C Gr1} : + Decidable_Membership + → Im g == Ker cz + → ∀ x : gr_set (Ker c), ∃ y, x ∈ C → y ∈ B ∧ (Happ g y = x)%G. +Proof. +intros * mem_dec sg x. +destruct (mem_dec C x) as [H2| H2]; [ | now exists 0%G ]. +enough (H : x ∈ Im g). { + simpl in H. + destruct H as (y & Hy & Hyx). + now exists y. +} +apply sg. +split; [ easy | ]. +now destruct (Happ cz x). +Qed. + +Theorem f'_is_inj {A' B'} {f' : HomGr A' B'} {za' : HomGr Gr1 A'} : + Im za' == Ker f' + → ∀ x y, x ∈ A' → y ∈ A' → (Happ f' x = Happ f' y)%G → (x = y)%G. +Proof. +intros * sf' * Hx Hy Hxy. +assert (H2 : (Happ f' x - Happ f' y = 0)%G). { + apply gr_sub_move_r. + now rewrite gr_add_0_l. +} +assert (H3 : (Happ f' (x - y) = 0)%G). { + rewrite Hadditive; [ | easy | now apply A' ]. + rewrite Hxy, Hopp; [ | easy ]. + apply gr_add_opp_r. +} +assert (H4 : (x - y)%G ∈ Ker f'). { + split; [ | apply H3 ]. + apply A'; [ easy | now apply A' ]. +} +apply sf' in H4. +simpl in H4. +destruct H4 as (z & _ & H4). +destruct z. +assert (H5 : (x - y = 0)%G). { + rewrite <- H4. + apply Hzero. +} +apply gr_sub_move_r in H5. +rewrite H5. +apply gr_add_0_l. +Qed. + +Theorem f'c_is_inj + {A A' B'} {f' : HomGr A' B'} {a : HomGr A A'} {za' : HomGr Gr1 A'} : + Im za' == Ker f' + → ∀ x y, x ∈ Coker a → y ∈ Coker a → + (Happ f' x = Happ f' y)%G → (x = y)%G. +Proof. +intros * sf' * Hx Hy Hxy. +simpl; unfold Coker_eq; simpl. +exists 0; split; [ apply A | ]. +eapply (f'_is_inj sf'); [ apply a, A | | ]. +-apply A'; [ easy | now apply A' ]. +-transitivity (Happ f' 0). + +apply f'; [ apply a, A | apply Hzero ]. + +rewrite Hzero; symmetry. + rewrite Hadditive; [ | easy | now apply A' ]. + rewrite Hxy, Hopp; [ | easy ]. + apply gr_add_opp_r. +Qed. + +Definition g₁_prop {B C C'} g (c : HomGr C C') g₁ := + ∀ x : gr_set (Ker c), x ∈ C → g₁ x ∈ B ∧ (Happ g (g₁ x) = x)%G. + +Definition f'₁_prop + {A A' B C B' C'} (a : HomGr A A') (b : HomGr B B') {c : HomGr C C'} + (f' : HomGr A' B') g₁ f'₁ := + ∀ x : gr_set B', + (∃ x1 : gr_set (Ker c), x1 ∈ Ker c ∧ (x = Happ b (g₁ x1))%G) + → f'₁ x ∈ Coker a ∧ (Happ f' (f'₁ x) = x)%G. + +Theorem g₁_in_B : ∀ {B C C' g} {c : HomGr C C'} {g₁}, + g₁_prop g c g₁ → ∀ x, x ∈ C → g₁ x ∈ B. +Proof. +intros * Hg₁ * Hx. +now specialize (Hg₁ x Hx) as H. +Qed. + +Theorem exists_B'_to_Coker_a : ∀ {A A' B B' C C' g f'} + {g' : HomGr B' C'} (a : HomGr A A') {b : HomGr B B'} {c : HomGr C C'} {g₁}, + Decidable_Membership + → Im f' == Ker g' + → g₁_prop g c g₁ + → diagram_commutes g b c g' + → ∀ y', ∃ z', + (∃ x, x ∈ Ker c ∧ (y' = Happ b (g₁ x))%G) + → z' ∈ Coker a ∧ (Happ f' z' = y')%G. +Proof. +intros * mem_dec sg' Hg₁ Hcgg' *. +destruct (mem_dec (Im b) y') as [Hy'| Hy']. +-destruct (mem_dec (Im f') y') as [(z' & Hz' & Hfz')| Hfy']. + +exists z'; now intros (x' & Hx' & Hyx'). + +exists 0%G; intros (x' & Hx' & Hyx'). + exfalso; apply Hfy', sg'; simpl. + split. + *destruct Hy' as (y & Hy & Hby). + eapply B'; [ apply Hby | now apply b ]. + *transitivity (Happ g' (Happ b (g₁ x'))). + --apply Happ_compat; [ | easy ]. + destruct Hy' as (y & Hy & Hby). + eapply B'; [ apply Hby | now apply b ]. + --rewrite <- Hcgg'. + destruct Hx' as (Hx', Hcx'). + specialize (Hg₁ x' Hx') as H2. + destruct H2 as (Hgx', Hggx'). + transitivity (Happ c x'); [ | easy ]. + apply c; [ now apply g, (g₁_in_B Hg₁) | easy ]. +-exists 0%G; intros (x' & Hx' & Hyx'). + exfalso; apply Hy'. + exists (g₁ x'). + split; [ apply (g₁_in_B Hg₁); now simpl in Hx' | ]. + now symmetry. +Qed. + +Theorem d_mem_compat + {A A' B B' C C'} {a : HomGr A A'} {b : HomGr B B'} {c : HomGr C C'} + {f' : HomGr A' B'} {g₁ f'₁} : + let d := λ x, f'₁ (Happ b (g₁ x)) in + f'₁_prop a b f' g₁ f'₁ + → ∀ x, x ∈ Ker c → d x ∈ Coker a. +Proof. +intros * Hf'₁ * Hx. +apply Hf'₁. +now exists x. +Qed. + +Theorem d_app_compat + {A A' B B' C C'} {a : HomGr A A'} {b : HomGr B B'} {c : HomGr C C'} + {f : HomGr A B} {g : HomGr B C} {f' : HomGr A' B'} {g' : HomGr B' C'} + {za' : HomGr Gr1 A'} {g₁ f'₁} : + diagram_commutes f a b f' + → diagram_commutes g b c g' + → Im f == Ker g + → Im za' == Ker f' + → Im f' == Ker g' + → g₁_prop g c g₁ + → f'₁_prop a b f' g₁ f'₁ + → let d := λ x, f'₁ (Happ b (g₁ x)) in + ∀ x1 x2, x1 ∈ Ker c → (x1 = x2)%G → (d x1 = d x2)%G. +Proof. +intros * Hcff' Hcgg' sf sf' sg' Hg₁ Hf'₁ * Hx1 Hxx. +assert (Hx2 : x2 ∈ Ker c) by now apply (gr_mem_compat _ x1). +assert (Hgy1 : (Happ g (g₁ x1) = x1)%G) by apply Hg₁, Hx1. +assert (Hgy2 : (Happ g (g₁ x2) = x2)%G) by apply Hg₁, Hx2. +assert (Hgb1 : (Happ g' (Happ b (g₁ x1)) = 0)%G). { + rewrite <- Hcgg'. + etransitivity; [ | apply Hx1 ]. + apply c; [ apply g, Hg₁, Hx1 | apply Hgy1 ]. +} +assert (Hgb2 : (Happ g' (Happ b (g₁ x2)) = 0)%G). { + rewrite <- Hcgg'. + etransitivity; [ | apply Hx2 ]. + apply c; [ apply g, Hg₁, Hx2 | apply Hgy2 ]. +} +assert (H1 : Happ b (g₁ x1) ∈ Im f'). { + apply sg'; split; [ apply b, (g₁_in_B Hg₁), Hx1 | easy ]. +} +assert (H2 : Happ b (g₁ x2) ∈ Im f'). { + apply sg'; split; [ apply b, (g₁_in_B Hg₁), Hx2 | easy ]. +} +destruct H1 as (z'1 & Hz'1 & Hfz'1). +destruct H2 as (z'2 & Hz'2 & Hfz'2). +move z'2 before z'1; move Hz'2 before Hz'1. +assert (H3 : (Happ f' (z'1 - z'2) = Happ b (g₁ x1 - g₁ x2))%G). { + rewrite Hadditive; [ | easy | now apply A' ]. + rewrite Hadditive. + -apply gr_add_compat; [ apply Hfz'1 | ]. + rewrite Hopp; [ | easy ]. + rewrite Hopp; [ | apply Hg₁, Hx2 ]. + now rewrite Hfz'2. + -apply (g₁_in_B Hg₁), Hx1. + -apply B, (g₁_in_B Hg₁), Hx2. +} +assert (H4 : g₁ x1 - g₁ x2 ∈ Im f). { + apply sf. + split. + -apply B; [ apply (g₁_in_B Hg₁), Hx1 | apply B, (g₁_in_B Hg₁), Hx2 ]. + -rewrite Hadditive; [ | apply Hg₁, Hx1 | apply B, Hg₁, Hx2 ]. + rewrite Hopp; [ | apply Hg₁, Hx2 ]. + apply gr_sub_move_r. + now rewrite Hgy1, Hgy2, gr_add_0_l. +} +destruct H4 as (z & Hz & Hfz). +assert (H4 : (z'1 - z'2 = Happ a z)%G). { + apply (f'_is_inj sf'); [ | now apply a | ]. + -apply A'; [ easy | now apply A' ]. + -rewrite <- Hcff', H3. + apply b; [ | now symmetry ]. + apply B; [ apply (g₁_in_B Hg₁), Hx1 | apply B, (g₁_in_B Hg₁), Hx2 ]. +} +assert (H6 : z'1 - z'2 ∈ Im a). { + exists z; split; [ easy | now symmetry ]. +} +assert (Hdx2 : (d x2 = z'2)%G). { + simpl; unfold Coker_eq; simpl. + exists 0. + split; [ apply A | ]. + rewrite Hzero; symmetry. + apply gr_sub_move_r; symmetry. + rewrite gr_add_0_l. + apply (f'_is_inj sf'); [ easy | now apply Hf'₁; exists x2 | ]. + rewrite Hfz'2; symmetry. + now apply Hf'₁; exists x2. +} +assert (Hdx1 : (d x1 = z'1)%G). { + simpl; unfold Coker_eq; simpl. + exists 0. + split; [ apply A | ]. + rewrite Hzero; symmetry. + apply gr_sub_move_r; symmetry. + rewrite gr_add_0_l. + apply (f'_is_inj sf'); [ easy | now apply Hf'₁; exists x1 | ]. + rewrite Hfz'1. + now symmetry; apply Hf'₁; exists x1. +} +assert (Hzz' : @gr_eq (@Coker A A' a) z'1 z'2). { + destruct H6 as (zz & Hzz & Hazz). + simpl; unfold Coker_eq; simpl. + now exists zz; split. +} +now rewrite Hdx1, Hzz'; symmetry. +Qed. + +Theorem d_additive + {A A' B B' C C'} {f : HomGr A B} {g : HomGr B C} {f' : HomGr A' B'} + {a : HomGr A A'} {b : HomGr B B'} {c : HomGr C C'} {za' : HomGr Gr1 A'} + {g₁ f'₁} : + diagram_commutes f a b f' + → Im f == Ker g + → Im za' == Ker f' + → g₁_prop g c g₁ + → f'₁_prop a b f' g₁ f'₁ + → let d := λ x, f'₁ (Happ b (g₁ x)) in + ∀ x1 x2, x1 ∈ Ker c → x2 ∈ Ker c → (d (x1 + x2) = d x1 + d x2)%G. +Proof. +intros * Hcff' sf sf' Hg₁ Hf'₁ * Hx1 Hx2. +set (x3 := (x1 + x2)%G). +set (y1 := g₁ x1). +set (y2 := g₁ x2). +set (y3 := g₁ x3). +set (z1 := d x1). +set (z2 := d x2). +set (z3 := d x3). +assert (H1 : (Happ g y1 = x1)%G) by now apply Hg₁; simpl in Hx1. +assert (H2 : (Happ g y2 = x2)%G) by now apply Hg₁; simpl in Hx2. +assert (H3 : (Happ g (y1 + y2)%G = x3)%G). { + rewrite Hadditive; [ now rewrite H1, H2 | | ]. + -apply (g₁_in_B Hg₁), Hx1. + -apply (g₁_in_B Hg₁), Hx2. +} +assert (Hy1 : y1 ∈ B) by apply (g₁_in_B Hg₁), Hx1. +assert (Hy2 : y2 ∈ B) by apply (g₁_in_B Hg₁), Hx2. +assert (Hy3 : y3 ∈ B) by (apply (g₁_in_B Hg₁), C; [ apply Hx1 | apply Hx2 ]). +assert (H4 : (y1 + y2 - y3)%G ∈ Ker g). { + split; [ now apply B; apply B | ]. + rewrite Hadditive; [ | now apply B | now apply B ]. + symmetry; apply gr_sub_move_r. + rewrite gr_add_0_l, Hopp; [ | easy ]. + rewrite gr_opp_involutive, H3. + apply Hg₁, C; [ apply Hx1 | apply Hx2 ]. +} +assert (Hfx1 : (Happ f' z1 = Happ b y1)%G). { + now apply Hf'₁; exists x1. +} +assert (Hfx2 : (Happ f' z2 = Happ b y2)%G). { + now apply Hf'₁; exists x2. +} +assert (Hfx3 : (Happ f' z3 = Happ b y3)%G). { + unfold z3, y3. + apply Hf'₁. + exists x3. + split; [ now apply (Ker c)| easy ]. +} +assert + (Hfzzz : + (Happ f' (z1 + z2 - z3) = Happ b y1 + Happ b y2 - Happ b y3)%G). { + assert (Hz1A' : z1 ∈ A' ∧ z2 ∈ A' ∧ z3 ∈ A'). { + assert (H : z1 ∈ A' ∧ z2 ∈ A'). { + split. + -now apply Hf'₁; exists x1. + -now apply Hf'₁; exists x2. + } + split; [ easy | ]. + split; [ easy | ]. + unfold z3. + apply Hf'₁. + exists x3; split; [ now apply (Ker c) | easy ]. + } + simpl; rewrite Hadditive; [ | now apply A' | now apply A' ]. + apply gr_add_compat. + -rewrite Hadditive; [ now apply gr_add_compat | easy | easy ]. + -rewrite Hopp; [ now apply gr_opp_compat | easy ]. +} +apply sf in H4. +destruct H4 as (z & Hz & Hzf). +assert (Hfz : (Happ f' (z1 + z2 - z3) = Happ f' (Happ a z))%G). { + rewrite Hfzzz. + etransitivity. + -apply gr_add_compat; [ now symmetry; apply b | now symmetry; apply Hopp ]. + -rewrite <- Hadditive; [ | now apply B | now apply B ]. + rewrite <- Hcff'. + apply b; [ | now apply B; apply B ]. + rewrite <- Hzf. + now apply f. +} +apply (f'_is_inj sf') in Hfz; [ | | now apply a ]. +-simpl; unfold Coker_eq; simpl. + exists (- z). + split; [ now apply A | ]. + rewrite Hopp; [ | easy ]. + rewrite <- Hfz. + symmetry; rewrite gr_add_comm. + rewrite gr_opp_add_distr. + apply gr_eq_opp_l. + rewrite gr_opp_add_distr. + simpl; apply gr_add_compat; [ | easy ]. + rewrite gr_opp_add_distr. + now do 2 rewrite gr_opp_involutive. +-apply A'. + +apply A'; [ now apply Hf'₁; exists x1 | now apply Hf'₁; exists x2 ]. + +apply A'. + apply Hf'₁; exists x3. + split; [ now apply (Ker c) | easy ]. +Qed. + +(* Ker a → Ker b → Ker c *) + +Theorem exact_sequence_1 {A B C A' B' C'} : + ∀ (f : HomGr A B) (g : HomGr B C) (f' : HomGr A' B') (g' : HomGr B' C') + (a : HomGr A A') (b : HomGr B B') (c : HomGr C C') (za' : HomGr Gr1 A') + (Hcff' : diagram_commutes f a b f') (Hcgg' : diagram_commutes g b c g'), + Im f == Ker g + → Im za' == Ker f' + → Im (HomGr_Ker_Ker a b Hcff') == Ker (HomGr_Ker_Ker b c Hcgg'). +Proof. +intros * sf sf'. +split. ++intros y (x & (Hx & Hax) & Hxy). + split; [ split | ]. + *eapply B; [ apply Hxy | now apply f ]. + *transitivity (Happ b (Happ f x)). + --apply b; [ | now symmetry ]. + eapply gr_mem_compat; [ apply Hxy | now apply f ]. + --rewrite Hcff'. + transitivity (Happ f' (@gr_zero A')); [ | apply Hzero ]. + apply f'; [ now apply a | easy ]. + *now apply sf; exists x. ++intros y ((Hy & Hby) & Hgy). + assert (H : y ∈ Im f) by now apply sf; split. + destruct H as (x & Hx & Hxy). + exists x; split; [ | easy ]. + split; [ easy | ]. + specialize (proj2 sf' (Happ a x)) as H1. + assert (H3 : Happ a x ∈ Ker f'). { + split; [ now apply a | ]. + rewrite <- Hcff'. + transitivity (Happ b y); [ | easy ]. + apply b; [ now apply f | easy ]. + } + specialize (H1 H3). + destruct H1 as (z & _ & Hzz). + rewrite <- Hzz. + destruct z. + apply Hzero. +Qed. + +(* Ker b → Ker c → CoKer a *) + +Theorem exact_sequence_2 {A B C A' B' C'} : + ∀ (f : HomGr A B) (g : HomGr B C) (f' : HomGr A' B') (g' : HomGr B' C') + (a : HomGr A A') (b : HomGr B B') (c : HomGr C C') (za' : HomGr Gr1 A') + (g₁ : gr_set (Ker c) → gr_set B) (f'₁ : gr_set B' → gr_set (Coker a)) + (sf : Im f == Ker g) (sf' : Im za' == Ker f') + (Hcff' : diagram_commutes f a b f') + (Hcgg' : diagram_commutes g b c g') + (Hg₁ : g₁_prop g c g₁) (Hf'₁ : f'₁_prop a b f' g₁ f'₁), + let d := λ x : gr_set (Ker c), f'₁ (Happ b (g₁ x)) in + ∀ (dm : HomGr (Ker c) (Coker a)), Happ dm = d + → Im (HomGr_Ker_Ker b c Hcgg') == Ker dm. +Proof. +intros *. +intros sf sf' Hcff' Hcgg' Hg₁ Hf'₁ d. +intros * Hd. +split. +-intros x (y & (Hy & Hay) & Hyx). + split; [ split | ]. + +eapply C; [ apply Hyx | now apply g ]. + +specialize (Hcgg' y) as H1. + transitivity (Happ c (Happ g y)). + *eapply c; [ | now apply C ]. + eapply C; [ apply Hyx | now apply g ]. + *rewrite H1. + transitivity (Happ g' (@gr_zero B')); [ | apply Hzero ]. + apply g'; [ now apply b | easy ]. + +simpl in Hyx. + assert (Hgy : Happ g y ∈ Ker c). { + split; [ now apply g | ]. + rewrite Hcgg'. + etransitivity; [ | apply Hzero ]. + apply g'; [ now apply b | easy ]. + } + assert (Hxk : x ∈ Ker c). { + assert (Hx : x ∈ C). { + eapply gr_mem_compat; [ apply Hyx | now apply g ]. + } + split; [ easy | ]. + etransitivity; [ | apply Hgy ]. + apply c; [ easy | now symmetry ]. + } + assert (Hyk : g₁ x - y ∈ Ker g). { + split. + -apply B; [ apply (g₁_in_B Hg₁), Hxk | now apply B ]. + -rewrite Hadditive; [ | apply (g₁_in_B Hg₁), Hxk | now apply B ]. + etransitivity. + *apply gr_add_compat; [ apply Hg₁, Hxk | ]. + now simpl; apply Hopp. + *apply gr_sub_move_r; rewrite <- Hyx. + symmetry; apply gr_add_0_l. + } + apply sf in Hyk. + destruct Hyk as (z & Hz & Haz). + assert (Hdx : (d x = Happ a z)%G). { + apply (f'c_is_inj sf'); [ | now apply a | ]. + -now apply (d_mem_compat Hf'₁). + -etransitivity; [ apply Hf'₁; now exists x | ]. + rewrite <- Hcff'; symmetry. + etransitivity. + +apply Happ_compat; [ apply Hmem_compat, Hz | apply Haz ]. + +rewrite Hadditive; [ | apply (g₁_in_B Hg₁), Hxk | now apply B ]. + etransitivity. + *apply gr_add_compat; [ easy | now simpl; apply Hopp ]. + *etransitivity. + --apply gr_add_compat; [ easy | apply gr_opp_compat, Hay ]. + --rewrite gr_sub_0_r. + apply b; [ apply (g₁_in_B Hg₁), Hxk | easy ]. + } + rewrite Hd. + simpl; rewrite Hdx. + exists z; split; [ easy | ]. + now simpl; rewrite gr_sub_0_r. +-intros x (Hx & z & Hz & Haz). + rewrite Hd in Haz. + simpl in x, Haz. + move z before x; move Hz before Hx. + rewrite gr_sub_0_r in Haz. + enough (∃ y, (y ∈ B ∧ (Happ b y = 0)%G) ∧ (Happ g y = x)%G) by easy. + apply (Happ_compat _ _ f') in Haz; [ | now apply a ]. + rewrite <- Hcff' in Haz. + exists (g₁ x - Happ f z). + split; [ split | ]. + +apply B; [ apply Hg₁, Hx | now apply B, f ]. + +rewrite Hadditive; [ | apply Hg₁, Hx | now apply B, f ]. + etransitivity. + *apply gr_add_compat; [ easy | now apply Hopp, f ]. + *apply gr_sub_move_r; rewrite gr_add_0_l; symmetry. + now rewrite Haz; apply Hf'₁; exists x. + +rewrite Hadditive; [ | apply Hg₁, Hx | now apply B, f ]. + *etransitivity. + --apply gr_add_compat; [ easy | now apply Hopp, f ]. + --apply gr_sub_move_l. + etransitivity; [ apply Hg₁, Hx | ]. + rewrite <- gr_add_0_l at 1. + apply gr_add_compat; [ | easy ]. + enough (H1 : Happ f z ∈ Ker g) by now simpl in H1. + now apply sf; exists z. +Qed. + +Theorem exact_sequence_3 {A B C A' B' C'} : + ∀ (f : HomGr A B) (g : HomGr B C) (f' : HomGr A' B') (g' : HomGr B' C') + (a : HomGr A A') (b : HomGr B B') (c : HomGr C C') (za' : HomGr Gr1 A') + (Hcff' : diagram_commutes f a b f') + (Hcgg' : diagram_commutes g b c g') + (sf : Im f == Ker g) (sf' : Im za' == Ker f') (sg' : Im f' == Ker g') + (g₁ : gr_set (Ker c) → gr_set B) + (f'₁ : gr_set B' → gr_set (Coker a)) + (Hg₁ : g₁_prop g c g₁) + (Hf'₁ : f'₁_prop a b f' g₁ f'₁), + let d := λ x : gr_set (Ker c), f'₁ (Happ b (g₁ x)) in + ∀ (dm : HomGr (Ker c) (Coker a)), Happ dm = d → + Im dm == Ker (HomGr_Coker_Coker a b Hcff'). +Proof. +intros *. +intros Hcgg' sf sf' sg' * Hg₁ Hf'₁ * Hdm. +split. +-intros z' Hz'. + destruct Hz' as (x & Hx & z & Hz & Haz). + move z before x. + rewrite Hdm in Haz. + simpl in Haz. + assert (Hz' : z' ∈ A'). { + apply gr_mem_compat with (x := d x - Happ a z). + -transitivity (d x - (d x - z')); simpl. + +apply gr_add_compat; [ easy | now apply gr_opp_compat ]. + +apply gr_sub_move_l. + rewrite gr_add_assoc; symmetry. + etransitivity; [ | apply gr_add_0_r ]. + apply gr_add_compat; [ easy | ]. + apply gr_add_opp_l. + -apply A'; [ now apply Hf'₁; exists x | now apply A', a ]. + } + simpl; split; [ easy | ]. + unfold Coker_eq; simpl. + enough (H : ∃ y, y ∈ B ∧ (Happ b y = Happ f' z')%G). { + destruct H as (y & Hy & Hby). + exists y. + split; [ easy | now rewrite gr_sub_0_r ]. + } + simpl in z'. + exists (g₁ x - Happ f z). + split. + +apply B; [ apply Hg₁, Hx | now apply B, f ]. + +apply (Happ_compat _ _ f') in Haz; [ | now apply a ]. + rewrite Hadditive; [ | apply Hg₁, Hx | now apply B, f ]. + etransitivity. + *apply gr_add_compat; [ easy | now apply Hopp, f ]. + *etransitivity. + --apply gr_add_compat; [ easy | ]. + apply gr_opp_compat, Hcff'. + --apply gr_sub_move_r. + etransitivity; [ now symmetry; apply Hf'₁; exists x | ]. + fold (d x). + apply gr_sub_move_l. + etransitivity. + ++apply gr_add_compat; [ easy | now symmetry; apply Hopp ]. + ++rewrite <- Hadditive; [ now symmetry | | now apply A' ]. + now apply Hf'₁; exists x. +-intros z' (Hz' & y & Hy & Hby). + simpl in z', Hz', Hby. + rewrite gr_sub_0_r in Hby. + simpl; unfold Coker_eq; simpl. + rewrite Hdm. + enough (H : + ∃ x, x ∈ C ∧ (Happ c x = 0)%G ∧ + ∃ z, z ∈ A ∧ (Happ a z = d x - z')%G). { + destruct H as (x & Hx). + now exists x. + } + exists (Happ g y). + split; [ now apply g | ]. + split. + +rewrite Hcgg'. + etransitivity. + *apply Happ_compat; [ now apply b | apply Hby ]. + *assert (H : Happ f' z' ∈ Im f') by now exists z'. + now apply sg' in H; simpl in H. + +assert (H : g₁ (Happ g y) - y ∈ Ker g). { + split. + -apply B; [ now apply Hg₁, g | now apply B ]. + -rewrite Hadditive; [ | now apply Hg₁, g | now apply B ]. + rewrite <- gr_add_opp_r. + apply gr_add_compat; [ now apply Hg₁, g | now apply Hopp ]. + } + apply sf in H. + destruct H as (z & Hz & Hfz). + exists z; split; [ easy | ]. + apply (Happ_compat _ _ b) in Hfz; [ | now apply f ]. + rewrite Hadditive in Hfz; [ | now apply Hg₁, g | now apply B ]. + rewrite Hcff' in Hfz. + *apply (f'_is_inj sf'); [ now apply a | | ]. + --apply A'; [ | now apply A' ]. + apply Hf'₁. + exists (Happ g y); split; [ | easy ]. + split; [ now apply g | ]. + rewrite Hcgg'. + etransitivity. + ++apply Happ_compat; [ now apply b | apply Hby ]. + ++assert (H : Happ f' z' ∈ Im f') by (exists z'; easy). + now apply sg' in H; simpl in H. + --rewrite Hfz. + symmetry; simpl; rewrite Hadditive; [ | | now apply A' ]. + ++apply gr_add_compat. + **apply Hf'₁. + exists (Happ g y); split; [ | easy ]. + split; [ now apply g | ]. + rewrite Hcgg'. + etransitivity. + ---apply Happ_compat; [ now apply b | apply Hby ]. + ---assert (H : Happ f' z' ∈ Im f') by (exists z'; easy). + now apply sg' in H; simpl in H. + **rewrite Hopp; [ | easy ]. + rewrite Hopp; [ | easy ]. + apply gr_opp_compat. + now symmetry. + ++apply Hf'₁; exists (Happ g y); split; [ | easy ]. + split; [ now apply g | ]. + rewrite Hcgg'. + etransitivity. + **apply Happ_compat; [ now apply b | apply Hby ]. + **assert (H : Happ f' z' ∈ Im f') by (exists z'; easy). + now apply sg' in H; simpl in H. +Qed. + +Theorem exact_sequence_4 {A B C A' B' C'} : + ∀ (f : HomGr A B) (g : HomGr B C) (f' : HomGr A' B') (g' : HomGr B' C') + (a : HomGr A A') (b : HomGr B B') (c : HomGr C C') + (Hcff' : diagram_commutes f a b f') + (Hcgg' : diagram_commutes g b c g') + (sg' : Im f' == Ker g') + (g₁ : gr_set (Ker c) → gr_set B) + (Hg₁ : g₁_prop g c g₁), + Im (HomGr_Coker_Coker a b Hcff') == Ker (HomGr_Coker_Coker b c Hcgg'). +Proof. +intros. +split. +-simpl. + intros y' (z' & Hz' & y & Hy & Hby). + simpl in Hby. + assert (Hb' : y' ∈ B'). { + symmetry in Hby. + apply gr_sub_move_r in Hby. + rewrite gr_add_comm in Hby. + apply gr_sub_move_r in Hby. + rewrite <- Hby. + apply B'; [ now apply f' | now apply B', b ]. + } + split; [ easy | ]. + unfold Coker_eq; simpl. + enough (H : ∃ x, x ∈ C ∧ (Happ c x = Happ g' y')%G). { + destruct H as (x & Hx & Hcx). + exists x; split; [ easy | ]. + rewrite Hcx; symmetry. + apply gr_sub_0_r. + } + exists (- Happ g y). + split; [ now apply C, g | ]. + rewrite Hopp, Hcgg'; [ | now apply g ]. + apply gr_eq_opp_l. + rewrite <- Hopp; [ | easy ]. + symmetry. + transitivity (Happ g' (Happ f' z' - y')). + +rewrite Hadditive; [ | now apply f' | now apply B' ]. + rewrite <- gr_add_0_l at 1. + apply gr_add_compat; [ | easy ]. + symmetry. + assert (H : Happ f' z' ∈ Im f') by (exists z'; easy). + now apply sg' in H; simpl in H. + +apply g'; [ | now symmetry ]. + apply B'; [ now apply f' | now apply B' ]. +-simpl; intros y' (Hy' & x & Hx & Hcx). + simpl in Hcx; rewrite gr_sub_0_r in Hcx. + unfold Coker_eq; simpl. + enough (H : ∃ y z', y ∈ B ∧ z' ∈ A' ∧ (Happ b y = Happ f' z' - y')%G). { + destruct H as (y & z' & Hz' & Hy & Hby). + exists z'; split; [ easy | ]. + now exists y. + } + assert (Hby : y' - Happ b (g₁ x) ∈ Ker g'). { + split. + -apply B'; [ easy | now apply B', b, Hg₁ ]. + -rewrite Hadditive; [ | easy | now apply B', b, Hg₁ ]. + rewrite <- Hcx, Hopp; [ | now apply b, Hg₁ ]. + rewrite <- Hcgg'. + etransitivity; [ | apply gr_add_opp_r ]. + apply gr_add_compat; [ easy | ]. + apply gr_opp_compat. + apply Happ_compat; [ now apply g, Hg₁ | now apply Hg₁ ]. + } + apply sg' in Hby. + destruct Hby as (z' & Hz' & Hfz'). + exists (- g₁ x), z'. + split; [ now apply B, Hg₁ | ]. + split; [ easy | ]. + rewrite Hfz', gr_add_comm, <- gr_add_assoc, gr_add_opp_l, gr_add_0_l. + now apply Hopp, Hg₁. +Qed. + +(* + f g cz + A------>B------>C------>0 + | | | + a| b| c| + | | | + v v v + 0----->A'----->B'----->C' + za' f' g' + + If the diagram is commutative, + and (f, g, cz) and (za', f', g') are exact sequences, + Then + there exists a morphism d from Ker c to Coker a, such that + Ker a→Ker b→Ker c→Coker a→Coker b→Coker c is an exact sequence. +*) + +Lemma snake : + ∀ (A B C A' B' C' : AbGroup) + (f : HomGr A B) (g : HomGr B C) + (f' : HomGr A' B') (g' : HomGr B' C') + (a : HomGr A A') (b : HomGr B B') (c : HomGr C C') + (cz : HomGr C Gr1) (za' : HomGr Gr1 A'), + Decidable_Membership * Choice + → diagram_commutes f a b f' + → diagram_commutes g b c g' + → exact_sequence [f; g; cz] + → exact_sequence [za'; f'; g'] + → ∃ (fk : HomGr (Ker a) (Ker b)) (gk : HomGr (Ker b) (Ker c)) + (fk' : HomGr (Coker a) (Coker b)) (gk' : HomGr (Coker b) (Coker c)), + ∃ (d : HomGr (Ker c) (Coker a)), + exact_sequence (Seq fk (Seq gk (Seq d (Seq fk' (Seq gk' SeqEnd))))). +Proof. +intros *. +intros (mem_dec, choice) Hcff' Hcgg' s s'. +exists (HomGr_Ker_Ker a b Hcff'). +exists (HomGr_Ker_Ker b c Hcgg'). +exists (HomGr_Coker_Coker a b Hcff'). +exists (HomGr_Coker_Coker b c Hcgg'). +destruct s as (sf & sg & _). +destruct s' as (sf' & sg' & _). +specialize (g_is_surj c mem_dec sg) as H1. +specialize (choice _ _ _ H1) as H; destruct H as (g₁, Hg₁). +specialize (exists_B'_to_Coker_a a mem_dec sg' Hg₁ Hcgg') as H2. +specialize (choice _ _ _ H2) as H; destruct H as (f'₁, Hf'₁). +fold (g₁_prop g c g₁) in Hg₁. +fold (f'₁_prop a b f' g₁ f'₁) in Hf'₁. +move f'₁ before g₁. +clear H1 H2. +set (d := λ x, f'₁ (Happ b (g₁ x))). +set + (dm := + {| Happ := d; + Hmem_compat := d_mem_compat Hf'₁; + Happ_compat := d_app_compat Hcff' Hcgg' sf sf' sg' Hg₁ Hf'₁; + Hadditive := d_additive Hcff' sf sf' Hg₁ Hf'₁ |}). +exists dm. +split; [ now eapply exact_sequence_1 | ]. +split; [ now eapply exact_sequence_2; try easy | ]. +split; [ now eapply exact_sequence_3; try easy | ]. +split; [ eapply exact_sequence_4; try easy; apply Hg₁ | easy ]. +Qed. + +Check snake. -- cgit v1.2.3