@@ -426,6 +426,27 @@ begin
426
426
{ rwa (is_colimit.desc' t _ _ _).2 .2 },
427
427
end
428
428
429
+ /--
430
+ The pushout cocone `(𝟙 X, 𝟙 X)` for the pair `(f, f)` is a colimit if `f` is an epi. The converse is
431
+ shown in `epi_of_is_colimit_mk_id_id`.
432
+ -/
433
+ def is_colimit_mk_id_id (f : X ⟶ Y) [epi f] :
434
+ is_colimit (mk (𝟙 Y) (𝟙 Y) rfl : pushout_cocone f f) :=
435
+ is_colimit.mk _
436
+ (λ s, s.inl)
437
+ (λ s, category.id_comp _)
438
+ (λ s, by rw [←cancel_epi f, category.id_comp, s.condition])
439
+ (λ s m m₁ m₂, by simpa using m₁)
440
+
441
+ /--
442
+ `f` is an epi if the pushout cocone `(𝟙 X, 𝟙 X)` is a colimit for the pair `(f, f)`.
443
+ The converse is given in `pushout_cocone.is_colimit_mk_id_id`.
444
+ -/
445
+ lemma epi_of_is_colimit_mk_id_id (f : X ⟶ Y)
446
+ (t : is_colimit (mk (𝟙 Y) (𝟙 Y) rfl : pushout_cocone f f)) :
447
+ epi f :=
448
+ ⟨λ Z g h eq, by { rcases pushout_cocone.is_colimit.desc' t _ _ eq with ⟨_, rfl, rfl⟩, refl }⟩
449
+
429
450
/-- Suppose `f` and `g` are two morphisms with a common domain and `s` is a colimit cocone over the
430
451
diagram formed by `f` and `g`. Suppose `f` and `g` both factor through an epimorphism `h` via
431
452
`x` and `y`, respectively. Then `s` is also a colimit cocone over the diagram formed by `x` and
@@ -614,6 +635,12 @@ pullback_cone.mono_snd_of_is_pullback_of_mono (limit.is_limit _)
614
635
(h₁ : pushout.inr ≫ k = pushout.inr ≫ l) : k = l :=
615
636
colimit.hom_ext $ pushout_cocone.coequalizer_ext _ h₀ h₁
616
637
638
+ /-- The pushout cocone built from the pushout coprojections is a pushout. -/
639
+ def pushout_is_pushout {X Y Z : C} (f : X ⟶ Y) (g : X ⟶ Z) [has_pushout f g] :
640
+ is_colimit (pushout_cocone.mk (pushout.inl : _ ⟶ pushout f g) pushout.inr pushout.condition) :=
641
+ pushout_cocone.is_colimit.mk _ (λ s, pushout.desc s.inl s.inr s.condition)
642
+ (by simp) (by simp) (by tidy)
643
+
617
644
/-- The pushout of an epimorphism is an epimorphism -/
618
645
instance pushout.inl_of_epi {X Y Z : C} {f : X ⟶ Y} {g : X ⟶ Z} [has_pushout f g] [epi g] :
619
646
epi (pushout.inl : Y ⟶ pushout f g) :=
@@ -661,6 +688,330 @@ by { ext; simp [← G.map_comp] }
661
688
662
689
end
663
690
691
+ section pullback_symmetry
692
+
693
+ open walking_cospan
694
+
695
+ variables (f : X ⟶ Z) (g : Y ⟶ Z)
696
+
697
+ /-- Making this a global instance would make the typeclass seach go in an infinite loop. -/
698
+ lemma has_pullback_symmetry [has_pullback f g] : has_pullback g f :=
699
+ ⟨⟨⟨pullback_cone.mk _ _ pullback.condition.symm,
700
+ pullback_cone.flip_is_limit (pullback_is_pullback _ _)⟩⟩⟩
701
+
702
+ local attribute [instance] has_pullback_symmetry
703
+
704
+ /-- The isomorphism `X ×[Z] Y ≅ Y ×[Z] X`. -/
705
+ def pullback_symmetry [has_pullback f g] :
706
+ pullback f g ≅ pullback g f :=
707
+ is_limit.cone_point_unique_up_to_iso
708
+ (pullback_cone.flip_is_limit (pullback_is_pullback f g) :
709
+ is_limit (pullback_cone.mk _ _ pullback.condition.symm))
710
+ (limit.is_limit _)
711
+
712
+ @[simp, reassoc] lemma pullback_symmetry_hom_comp_fst [has_pullback f g] :
713
+ (pullback_symmetry f g).hom ≫ pullback.fst = pullback.snd := by simp [pullback_symmetry]
714
+
715
+ @[simp, reassoc] lemma pullback_symmetry_hom_comp_snd [has_pullback f g] :
716
+ (pullback_symmetry f g).hom ≫ pullback.snd = pullback.fst := by simp [pullback_symmetry]
717
+
718
+ @[simp, reassoc] lemma pullback_symmetry_inv_comp_fst [has_pullback f g] :
719
+ (pullback_symmetry f g).inv ≫ pullback.fst = pullback.snd := by simp [iso.inv_comp_eq]
720
+
721
+ @[simp, reassoc] lemma pullback_symmetry_inv_comp_snd [has_pullback f g] :
722
+ (pullback_symmetry f g).inv ≫ pullback.snd = pullback.fst := by simp [iso.inv_comp_eq]
723
+
724
+ end pullback_symmetry
725
+
726
+ section pushout_symmetry
727
+
728
+ open walking_cospan
729
+
730
+ variables (f : X ⟶ Y) (g : X ⟶ Z)
731
+
732
+ /-- Making this a global instance would make the typeclass seach go in an infinite loop. -/
733
+ lemma has_pushout_symmetry [has_pushout f g] : has_pushout g f :=
734
+ ⟨⟨⟨pushout_cocone.mk _ _ pushout.condition.symm,
735
+ pushout_cocone.flip_is_colimit (pushout_is_pushout _ _)⟩⟩⟩
736
+
737
+ local attribute [instance] has_pushout_symmetry
738
+
739
+ /-- The isomorphism `Y ⨿[X] Z ≅ Z ⨿[X] Y`. -/
740
+ def pushout_symmetry [has_pushout f g] :
741
+ pushout f g ≅ pushout g f :=
742
+ is_colimit.cocone_point_unique_up_to_iso
743
+ (pushout_cocone.flip_is_colimit (pushout_is_pushout f g) :
744
+ is_colimit (pushout_cocone.mk _ _ pushout.condition.symm))
745
+ (colimit.is_colimit _)
746
+
747
+ @[simp, reassoc] lemma inl_comp_pushout_symmetry_hom [has_pushout f g] :
748
+ pushout.inl ≫ (pushout_symmetry f g).hom = pushout.inr :=
749
+ (colimit.is_colimit (span f g)).comp_cocone_point_unique_up_to_iso_hom
750
+ (pushout_cocone.flip_is_colimit (pushout_is_pushout g f)) _
751
+
752
+ @[simp, reassoc] lemma inr_comp_pushout_symmetry_hom [has_pushout f g] :
753
+ pushout.inr ≫ (pushout_symmetry f g).hom = pushout.inl :=
754
+ (colimit.is_colimit (span f g)).comp_cocone_point_unique_up_to_iso_hom
755
+ (pushout_cocone.flip_is_colimit (pushout_is_pushout g f)) _
756
+
757
+ @[simp, reassoc] lemma inl_comp_pushout_symmetry_inv [has_pushout f g] :
758
+ pushout.inl ≫ (pushout_symmetry f g).inv = pushout.inr := by simp [iso.comp_inv_eq]
759
+
760
+ @[simp, reassoc] lemma inr_comp_pushout_symmetry_inv [has_pushout f g] :
761
+ pushout.inr ≫ (pushout_symmetry f g).inv = pushout.inl := by simp [iso.comp_inv_eq]
762
+
763
+ end pushout_symmetry
764
+
765
+ section pullback_left_iso
766
+
767
+ open walking_cospan
768
+
769
+ variables (f : X ⟶ Z) (g : Y ⟶ Z) [is_iso f]
770
+
771
+ /-- If `f : X ⟶ Z` is iso, then `X ×[Z] Y ≅ Y`. This is the explicit limit cone. -/
772
+ def pullback_cone_of_left_iso : pullback_cone f g :=
773
+ pullback_cone.mk (g ≫ inv f) (𝟙 _) $ by simp
774
+
775
+ @[simp] lemma pullback_cone_of_left_iso_X :
776
+ (pullback_cone_of_left_iso f g).X = Y := rfl
777
+
778
+ @[simp] lemma pullback_cone_of_left_iso_fst :
779
+ (pullback_cone_of_left_iso f g).fst = g ≫ inv f := rfl
780
+
781
+ @[simp] lemma pullback_cone_of_left_iso_snd :
782
+ (pullback_cone_of_left_iso f g).snd = 𝟙 _ := rfl
783
+
784
+ @[simp] lemma pullback_cone_of_left_iso_π_app_none :
785
+ (pullback_cone_of_left_iso f g).π.app none = g := by { delta pullback_cone_of_left_iso, simp }
786
+
787
+ @[simp] lemma pullback_cone_of_left_iso_π_app_left :
788
+ (pullback_cone_of_left_iso f g).π.app left = g ≫ inv f := rfl
789
+
790
+ @[simp] lemma pullback_cone_of_left_iso_π_app_right :
791
+ (pullback_cone_of_left_iso f g).π.app right = 𝟙 _ := rfl
792
+
793
+ /-- Verify that the constructed limit cone is indeed a limit. -/
794
+ def pullback_cone_of_left_iso_is_limit :
795
+ is_limit (pullback_cone_of_left_iso f g) :=
796
+ pullback_cone.is_limit_aux' _ (λ s, ⟨s.snd, by simp [← s.condition_assoc]⟩)
797
+
798
+ lemma has_pullback_of_left_iso : has_pullback f g :=
799
+ ⟨⟨⟨_, pullback_cone_of_left_iso_is_limit f g⟩⟩⟩
800
+
801
+ local attribute [instance] has_pullback_of_left_iso
802
+
803
+ instance pullback_snd_iso_of_left_iso : is_iso (pullback.snd : pullback f g ⟶ _) :=
804
+ begin
805
+ refine ⟨⟨pullback.lift (g ≫ inv f) (𝟙 _) (by simp), _, by simp⟩⟩,
806
+ ext,
807
+ { simp [← pullback.condition_assoc] },
808
+ { simp [pullback.condition_assoc] },
809
+ end
810
+
811
+ end pullback_left_iso
812
+
813
+ section pullback_right_iso
814
+
815
+ open walking_cospan
816
+
817
+ variables (f : X ⟶ Z) (g : Y ⟶ Z) [is_iso g]
818
+
819
+ /-- If `g : Y ⟶ Z` is iso, then `X ×[Z] Y ≅ X`. This is the explicit limit cone. -/
820
+ def pullback_cone_of_right_iso : pullback_cone f g :=
821
+ pullback_cone.mk (𝟙 _) (f ≫ inv g) $ by simp
822
+
823
+ @[simp] lemma pullback_cone_of_right_iso_X :
824
+ (pullback_cone_of_right_iso f g).X = X := rfl
825
+
826
+ @[simp] lemma pullback_cone_of_right_iso_fst :
827
+ (pullback_cone_of_right_iso f g).fst = 𝟙 _ := rfl
828
+
829
+ @[simp] lemma pullback_cone_of_right_iso_snd :
830
+ (pullback_cone_of_right_iso f g).snd = f ≫ inv g := rfl
831
+
832
+ @[simp] lemma pullback_cone_of_right_iso_π_app_none :
833
+ (pullback_cone_of_right_iso f g).π.app none = f := category.id_comp _
834
+
835
+ @[simp] lemma pullback_cone_of_right_iso_π_app_left :
836
+ (pullback_cone_of_right_iso f g).π.app left = 𝟙 _ := rfl
837
+
838
+ @[simp] lemma pullback_cone_of_right_iso_π_app_right :
839
+ (pullback_cone_of_right_iso f g).π.app right = f ≫ inv g := rfl
840
+
841
+ /-- Verify that the constructed limit cone is indeed a limit. -/
842
+ def pullback_cone_of_right_iso_is_limit :
843
+ is_limit (pullback_cone_of_right_iso f g) :=
844
+ pullback_cone.is_limit_aux' _ (λ s, ⟨s.fst, by simp [s.condition_assoc]⟩)
845
+
846
+ lemma has_pullback_of_right_iso : has_pullback f g :=
847
+ ⟨⟨⟨_, pullback_cone_of_right_iso_is_limit f g⟩⟩⟩
848
+
849
+ local attribute [instance] has_pullback_of_right_iso
850
+
851
+ instance pullback_snd_iso_of_right_iso : is_iso (pullback.fst : pullback f g ⟶ _) :=
852
+ begin
853
+ refine ⟨⟨pullback.lift (𝟙 _) (f ≫ inv g) (by simp), _, by simp⟩⟩,
854
+ ext,
855
+ { simp },
856
+ { simp [pullback.condition_assoc] },
857
+ end
858
+
859
+ end pullback_right_iso
860
+
861
+ section pushout_left_iso
862
+
863
+ open walking_span
864
+
865
+ variables (f : X ⟶ Y) (g : X ⟶ Z) [is_iso f]
866
+
867
+ /-- If `f : X ⟶ Y` is iso, then `Y ⨿[X] Z ≅ Z`. This is the explicit colimit cocone. -/
868
+ def pushout_cocone_of_left_iso : pushout_cocone f g :=
869
+ pushout_cocone.mk (inv f ≫ g) (𝟙 _) $ by simp
870
+
871
+ @[simp] lemma pushout_cocone_of_left_iso_X :
872
+ (pushout_cocone_of_left_iso f g).X = Z := rfl
873
+
874
+ @[simp] lemma pushout_cocone_of_left_iso_inl :
875
+ (pushout_cocone_of_left_iso f g).inl = inv f ≫ g := rfl
876
+
877
+ @[simp] lemma pushout_cocone_of_left_iso_inr :
878
+ (pushout_cocone_of_left_iso f g).inr = 𝟙 _ := rfl
879
+
880
+ @[simp] lemma pushout_cocone_of_left_iso_ι_app_none :
881
+ (pushout_cocone_of_left_iso f g).ι.app none = g := by { delta pushout_cocone_of_left_iso, simp }
882
+
883
+ @[simp] lemma pushout_cocone_of_left_iso_ι_app_left :
884
+ (pushout_cocone_of_left_iso f g).ι.app left = inv f ≫ g := rfl
885
+
886
+ @[simp] lemma pushout_cocone_of_left_iso_ι_app_right :
887
+ (pushout_cocone_of_left_iso f g).ι.app right = 𝟙 _ := rfl
888
+
889
+ /-- Verify that the constructed cocone is indeed a colimit. -/
890
+ def pushout_cocone_of_left_iso_is_limit :
891
+ is_colimit (pushout_cocone_of_left_iso f g) :=
892
+ pushout_cocone.is_colimit_aux' _ (λ s, ⟨s.inr, by simp [← s.condition]⟩)
893
+
894
+ lemma has_pushout_of_left_iso : has_pushout f g :=
895
+ ⟨⟨⟨_, pushout_cocone_of_left_iso_is_limit f g⟩⟩⟩
896
+
897
+ local attribute [instance] has_pushout_of_left_iso
898
+
899
+ instance pushout_inr_iso_of_left_iso : is_iso (pushout.inr : _ ⟶ pushout f g) :=
900
+ begin
901
+ refine ⟨⟨pushout.desc (inv f ≫ g) (𝟙 _) (by simp), (by simp), _⟩⟩,
902
+ ext,
903
+ { simp [← pushout.condition] },
904
+ { simp [pushout.condition_assoc] },
905
+ end
906
+
907
+ end pushout_left_iso
908
+
909
+ section pushout_right_iso
910
+
911
+ open walking_span
912
+
913
+ variables (f : X ⟶ Y) (g : X ⟶ Z) [is_iso g]
914
+
915
+ /-- If `f : X ⟶ Z` is iso, then `Y ⨿[X] Z ≅ Y`. This is the explicit colimit cocone. -/
916
+ def pushout_cocone_of_right_iso : pushout_cocone f g :=
917
+ pushout_cocone.mk (𝟙 _) (inv g ≫ f) $ by simp
918
+
919
+ @[simp] lemma pushout_cocone_of_right_iso_X :
920
+ (pushout_cocone_of_right_iso f g).X = Y := rfl
921
+
922
+ @[simp] lemma pushout_cocone_of_right_iso_inl :
923
+ (pushout_cocone_of_right_iso f g).inl = 𝟙 _ := rfl
924
+
925
+ @[simp] lemma pushout_cocone_of_right_iso_inr :
926
+ (pushout_cocone_of_right_iso f g).inr = inv g ≫ f := rfl
927
+
928
+ @[simp] lemma pushout_cocone_of_right_iso_ι_app_none :
929
+ (pushout_cocone_of_right_iso f g).ι.app none = f := by { delta pushout_cocone_of_right_iso, simp }
930
+
931
+ @[simp] lemma pushout_cocone_of_right_iso_ι_app_left :
932
+ (pushout_cocone_of_right_iso f g).ι.app left = 𝟙 _ := rfl
933
+
934
+ @[simp] lemma pushout_cocone_of_right_iso_ι_app_right :
935
+ (pushout_cocone_of_right_iso f g).ι.app right = inv g ≫ f := rfl
936
+
937
+ /-- Verify that the constructed cocone is indeed a colimit. -/
938
+ def pushout_cocone_of_right_iso_is_limit :
939
+ is_colimit (pushout_cocone_of_right_iso f g) :=
940
+ pushout_cocone.is_colimit_aux' _ (λ s, ⟨s.inl, by simp [←s.condition]⟩)
941
+
942
+ lemma has_pushout_of_right_iso : has_pushout f g :=
943
+ ⟨⟨⟨_, pushout_cocone_of_right_iso_is_limit f g⟩⟩⟩
944
+
945
+ local attribute [instance] has_pushout_of_right_iso
946
+
947
+ instance pushout_inl_iso_of_right_iso : is_iso (pushout.inl : _ ⟶ pushout f g) :=
948
+ begin
949
+ refine ⟨⟨pushout.desc (𝟙 _) (inv g ≫ f) (by simp), (by simp), _⟩⟩,
950
+ ext,
951
+ { simp [←pushout.condition] },
952
+ { simp [pushout.condition] },
953
+ end
954
+
955
+ end pushout_right_iso
956
+
957
+ section
958
+
959
+ open walking_cospan
960
+
961
+ variable (f : X ⟶ Y)
962
+
963
+ instance has_kernel_pair_of_mono [mono f] : has_pullback f f :=
964
+ ⟨⟨⟨_, pullback_cone.is_limit_mk_id_id f⟩⟩⟩
965
+
966
+ lemma fst_eq_snd_of_mono_eq [mono f] : (pullback.fst : pullback f f ⟶ _) = pullback.snd :=
967
+ ((pullback_cone.is_limit_mk_id_id f).fac (get_limit_cone (cospan f f)).cone left).symm.trans
968
+ ((pullback_cone.is_limit_mk_id_id f).fac (get_limit_cone (cospan f f)).cone right : _)
969
+
970
+ @[simp] lemma pullback_symmetry_hom_of_mono_eq [mono f] :
971
+ (pullback_symmetry f f).hom = 𝟙 _ := by ext; simp [fst_eq_snd_of_mono_eq]
972
+
973
+ instance fst_iso_of_mono_eq [mono f] : is_iso (pullback.fst : pullback f f ⟶ _) :=
974
+ begin
975
+ refine ⟨⟨pullback.lift (𝟙 _) (𝟙 _) (by simp), _, by simp⟩⟩,
976
+ ext,
977
+ { simp },
978
+ { simp [fst_eq_snd_of_mono_eq] }
979
+ end
980
+
981
+ instance snd_iso_of_mono_eq [mono f] : is_iso (pullback.snd : pullback f f ⟶ _) :=
982
+ by { rw ← fst_eq_snd_of_mono_eq, apply_instance }
983
+
984
+ end
985
+
986
+ section
987
+
988
+ open walking_span
989
+
990
+ variable (f : X ⟶ Y)
991
+
992
+ instance has_cokernel_pair_of_epi [epi f] : has_pushout f f :=
993
+ ⟨⟨⟨_, pushout_cocone.is_colimit_mk_id_id f⟩⟩⟩
994
+
995
+ lemma inl_eq_inr_of_epi_eq [epi f] : (pushout.inl : _ ⟶ pushout f f) = pushout.inr :=
996
+ ((pushout_cocone.is_colimit_mk_id_id f).fac (get_colimit_cocone (span f f)).cocone left).symm.trans
997
+ ((pushout_cocone.is_colimit_mk_id_id f).fac (get_colimit_cocone (span f f)).cocone right : _)
998
+
999
+ @[simp] lemma pullback_symmetry_hom_of_epi_eq [epi f] :
1000
+ (pushout_symmetry f f).hom = 𝟙 _ := by ext; simp [inl_eq_inr_of_epi_eq]
1001
+
1002
+ instance inl_iso_of_epi_eq [epi f] : is_iso (pushout.inl : _ ⟶ pushout f f) :=
1003
+ begin
1004
+ refine ⟨⟨pushout.desc (𝟙 _) (𝟙 _) (by simp), by simp, _⟩⟩,
1005
+ ext,
1006
+ { simp },
1007
+ { simp [inl_eq_inr_of_epi_eq] }
1008
+ end
1009
+
1010
+ instance inr_iso_of_epi_eq [epi f] : is_iso (pushout.inr : _ ⟶ pushout f f) :=
1011
+ by { rw ← inl_eq_inr_of_epi_eq, apply_instance }
1012
+
1013
+ end
1014
+
664
1015
variables (C)
665
1016
666
1017
/--
0 commit comments