1-- Initial, terminal, and zero objects2-- Part of Cumulus, the Grace17 mathematics library.3-- Copyright (c) 2026 Grant Passmore.4-- Released under the Apache License 2.0. See LICENSE in the repository root.5-- Authors: Grant Passmore67module Grace.Cumulus.Category.Terminal8import MonoEpi910-- A terminal object receives exactly one morphism from each object, an11-- initial object sends exactly one morphism to each object.12predicate Terminal (C t : Set) :=13 t ∈ obj(C) ∧ (∀ a ∈ obj(C), ∃ f ∈ hom(C, a, t),14∀ g ∈ hom(C, a, t), g = f)1516predicate Initial (C i : Set) :=17 i ∈ obj(C) ∧ (∀ a ∈ obj(C), ∃ f ∈ hom(C, i, a),18∀ g ∈ hom(C, i, a), g = f)1920predicate ZeroObject (C z : Set) :=21 Initial(C, z) ∧ Terminal(C, z)2223theorem Terminal.object (C t : Set)24requires terminal : Terminal(C, t)25shows t ∈ obj(C)26proof27obtain⟨tInO, universal⟩:= terminal28exact tInO2930theorem Terminal.exists_morphism (C t a : Set)31requires terminal : Terminal(C, t)32requires aInO : a ∈ obj(C)33shows∃ f ∈ hom(C, a, t), ∀ g ∈ hom(C, a, t), g = f34proof35obtain⟨tInO, universal⟩:= terminal36exact universal with a, aInO3738theorem Terminal.unique_morphism (C t a f g : Set)39requires terminal : Terminal(C, t)40requires aInO : a ∈ obj(C)41requires fHom : f ∈ hom(C, a, t)42requires gHom : g ∈ hom(C, a, t)43shows f = g44proof45obtain⟨u, uHom, unique⟩:= Terminal.exists_morphism with terminal, aInO46have fEqual := unique with f, fHom47have gEqual := unique with g, gHom48cc4950theorem Initial.object (C i : Set)51requires initial : Initial(C, i)52shows i ∈ obj(C)53proof54obtain⟨iInO, universal⟩:= initial55exact iInO5657theorem Initial.exists_morphism (C i a : Set)58requires initial : Initial(C, i)59requires aInO : a ∈ obj(C)60shows∃ f ∈ hom(C, i, a), ∀ g ∈ hom(C, i, a), g = f61proof62obtain⟨iInO, universal⟩:= initial63exact universal with a, aInO6465theorem Initial.unique_morphism (C i a f g : Set)66requires initial : Initial(C, i)67requires aInO : a ∈ obj(C)68requires fHom : f ∈ hom(C, i, a)69requires gHom : g ∈ hom(C, i, a)70shows f = g71proof72obtain⟨u, uHom, unique⟩:= Initial.exists_morphism with initial, aInO73have fEqual := unique with f, fHom74have gEqual := unique with g, gHom75cc7677theorem ZeroObject.initial (C z : Set)78requires zero : ZeroObject(C, z)79shows Initial(C, z)80proof81simp [ZeroObject]8283theorem ZeroObject.terminal (C z : Set)84requires zero : ZeroObject(C, z)85shows Terminal(C, z)86proof87simp [ZeroObject]8889theorem ZeroObject.object (C z : Set)90requires zero : ZeroObject(C, z)91shows z ∈ obj(C)92proof93have initial := ZeroObject.initial with zero94exact Initial.object with initial9596-- The only endomorphism of a terminal or initial object is its identity.97theorem Terminal.endomorphism (C t f : Set)98requires category : Category(C)99requires terminal : Terminal(C, t)100requires fHom : f ∈ hom(C, t, t)101shows f = id(C)(t)102proof103have tInO := Terminal.object with terminal104have idHom := hom.id with category, tInO105exact Terminal.unique_morphism with terminal, tInO, fHom, idHom106107theorem Initial.endomorphism (C i f : Set)108requires category : Category(C)109requires initial : Initial(C, i)110requires fHom : f ∈ hom(C, i, i)111shows f = id(C)(i)112proof113have iInO := Initial.object with initial114have idHom := hom.id with category, iInO115exact Initial.unique_morphism with initial, iInO, fHom, idHom116117-- Terminal objects are isomorphic through a unique isomorphism.118theorem Terminal.inverse_pair (C t u f g : Set)119requires category : Category(C)120requires tTerminal : Terminal(C, t)121requires uTerminal : Terminal(C, u)122requires fHom : f ∈ hom(C, t, u)123requires gHom : g ∈ hom(C, u, t)124shows InversePair(C, f, g)125proof126have gfHom := hom.comp with category, gHom, fHom127have fgHom := hom.comp with category, fHom, gHom128have gfId := Terminal.endomorphism with category, tTerminal, gfHom129have fgId := Terminal.endomorphism with category, uTerminal, fgHom130have fInM := hom.in_morphisms with fHom131have gInM := hom.in_morphisms with gHom132have domF := hom.dom with fHom133have codF := hom.cod with fHom134have domG := hom.dom with gHom135have codG := hom.cod with gHom136unfold InversePair137refine⟨fInM, gInM, ?_, ?_, ?_, ?_⟩138 . cc139 . cc140 . cc141 . cc142143theorem Terminal.isomorphism (C t u f : Set)144requires category : Category(C)145requires tTerminal : Terminal(C, t)146requires uTerminal : Terminal(C, u)147requires fHom : f ∈ hom(C, t, u)148shows Isomorphism(C, f)149proof150have tInO := Terminal.object with tTerminal151obtain⟨g, gHom, unique⟩:= Terminal.exists_morphism with152 tTerminal, uTerminal.left153have pair := Terminal.inverse_pair with154 category, tTerminal, uTerminal, fHom, gHom155exact Isomorphism.of_pair with pair156157theorem Terminal.isomorphic (C t u : Set)158requires category : Category(C)159requires tTerminal : Terminal(C, t)160requires uTerminal : Terminal(C, u)161shows Isomorphic(C, t, u)162proof163have tInO := Terminal.object with tTerminal164obtain⟨f, fHom, unique⟩:= Terminal.exists_morphism with uTerminal, tInO165have iso := Terminal.isomorphism with category, tTerminal, uTerminal, fHom166exact Isomorphic.of_hom with fHom, iso167168theorem Terminal.unique_isomorphism (C t u f g : Set)169requires tTerminal : Terminal(C, t)170requires uTerminal : Terminal(C, u)171requires fHom : f ∈ hom(C, t, u)172requires gHom : g ∈ hom(C, t, u)173shows f = g174proof175have tInO := Terminal.object with tTerminal176exact Terminal.unique_morphism with uTerminal, tInO, fHom, gHom177178theorem Initial.inverse_pair (C i j f g : Set)179requires category : Category(C)180requires iInitial : Initial(C, i)181requires jInitial : Initial(C, j)182requires fHom : f ∈ hom(C, i, j)183requires gHom : g ∈ hom(C, j, i)184shows InversePair(C, f, g)185proof186have gfHom := hom.comp with category, gHom, fHom187have fgHom := hom.comp with category, fHom, gHom188have gfId := Initial.endomorphism with category, iInitial, gfHom189have fgId := Initial.endomorphism with category, jInitial, fgHom190have fInM := hom.in_morphisms with fHom191have gInM := hom.in_morphisms with gHom192have domF := hom.dom with fHom193have codF := hom.cod with fHom194have domG := hom.dom with gHom195have codG := hom.cod with gHom196unfold InversePair197refine⟨fInM, gInM, ?_, ?_, ?_, ?_⟩198 . cc199 . cc200 . cc201 . cc202203theorem Initial.isomorphism (C i j f : Set)204requires category : Category(C)205requires iInitial : Initial(C, i)206requires jInitial : Initial(C, j)207requires fHom : f ∈ hom(C, i, j)208shows Isomorphism(C, f)209proof210have iInO := Initial.object with iInitial211obtain⟨g, gHom, unique⟩:= Initial.exists_morphism with jInitial, iInO212have pair := Initial.inverse_pair with213 category, iInitial, jInitial, fHom, gHom214exact Isomorphism.of_pair with pair215216theorem Initial.isomorphic (C i j : Set)217requires category : Category(C)218requires iInitial : Initial(C, i)219requires jInitial : Initial(C, j)220shows Isomorphic(C, i, j)221proof222have jInO := Initial.object with jInitial223obtain⟨f, fHom, unique⟩:= Initial.exists_morphism with iInitial, jInO224have iso := Initial.isomorphism with category, iInitial, jInitial, fHom225exact Isomorphic.of_hom with fHom, iso226227theorem Initial.unique_isomorphism (C i j f g : Set)228requires iInitial : Initial(C, i)229requires jInitial : Initial(C, j)230requires fHom : f ∈ hom(C, i, j)231requires gHom : g ∈ hom(C, i, j)232shows f = g233proof234have jInO := Initial.object with jInitial235exact Initial.unique_morphism with iInitial, jInO, fHom, gHom236237theorem ZeroObject.isomorphic (C z w : Set)238requires category : Category(C)239requires zZero : ZeroObject(C, z)240requires wZero : ZeroObject(C, w)241shows Isomorphic(C, z, w)242proof243have zTerminal := ZeroObject.terminal with zZero244have wTerminal := ZeroObject.terminal with wZero245exact Terminal.isomorphic with category, zTerminal, wTerminal246247-- Being terminal or initial is invariant under isomorphism.248theorem Terminal.of_isomorphic (C t u : Set)249requires category : Category(C)250requires terminal : Terminal(C, t)251requires iso : Isomorphic(C, t, u)252shows Terminal(C, u)253proof254obtain⟨f, fHom, g, pair⟩:= iso255have gHom := InversePair.in_hom with pair, fHom256have uInO := hom.cod with fHom257have fInM := hom.in_morphisms with fHom258have uIn : u ∈ obj(C)259have codIn := Category.cod_closed with category, fInM260 rwa uInO at codIn261unfold Terminal262refine⟨uIn, ?_⟩263intros a aInO264obtain⟨v, vHom, unique⟩:= Terminal.exists_morphism with terminal, aInO265have fvHom := hom.comp with category, fHom, vHom266refine⟨f ∘ v, fvHom, ?_⟩267intros h hHom268have ghHom := hom.comp with category, gHom, hHom269have ghEqual := unique with g ∘ h, ghHom270have assoc := Category.assoc_hom with category, fHom, gHom, hHom271have unitH := Category.id_left_hom with category, hHom272have fgId : f ∘ g = id(C)(u)273have law := InversePair.right with pair274have codF := hom.cod with fHom275 rwa codF at law276calc277 h = id(C)(u) ∘ h :=byrw unitH278 _ = (f ∘ g) ∘ h :=byrw fgId279 _ = f ∘ (g ∘ h) := assoc280 _ = f ∘ v :=byrw ghEqual281282theorem Initial.of_isomorphic (C i j : Set)283requires category : Category(C)284requires initial : Initial(C, i)285requires iso : Isomorphic(C, i, j)286shows Initial(C, j)287proof288obtain⟨f, fHom, g, pair⟩:= iso289have gHom := InversePair.in_hom with pair, fHom290have jInO := hom.cod with fHom291have fInM := hom.in_morphisms with fHom292have jIn : j ∈ obj(C)293have codIn := Category.cod_closed with category, fInM294 rwa jInO at codIn295unfold Initial296refine⟨jIn, ?_⟩297intros a aInO298obtain⟨v, vHom, unique⟩:= Initial.exists_morphism with initial, aInO299have vgHom := hom.comp with category, vHom, gHom300refine⟨v ∘ g, vgHom, ?_⟩301intros h hHom302have hfHom := hom.comp with category, hHom, fHom303have hfEqual := unique with h ∘ f, hfHom304have assoc := Category.assoc_hom with category, hHom, fHom, gHom305have unitH := Category.id_right_hom with category, hHom306have fgId : f ∘ g = id(C)(j)307have law := InversePair.right with pair308have codF := hom.cod with fHom309 rwa codF at law310calc311 h = h ∘ id(C)(j) :=byrw unitH312 _ = h ∘ (f ∘ g) :=byrw fgId313 _ = (h ∘ f) ∘ g :=byrw assoc314 _ = v ∘ g :=byrw hfEqual315316-- Every morphism into a terminal object is a split epimorphism when its317-- domain is itself terminal, and every morphism from a terminal object is318-- a split monomorphism.319theorem Terminal.split_mono (C t a f : Set)320requires category : Category(C)321requires terminal : Terminal(C, t)322requires aInO : a ∈ obj(C)323requires fHom : f ∈ hom(C, t, a)324shows SplitMonomorphism(C, f)325proof326obtain⟨r, rHom, unique⟩:= Terminal.exists_morphism with terminal, aInO327have rfHom := hom.comp with category, rHom, fHom328have rfId := Terminal.endomorphism with category, terminal, rfHom329have fInM := hom.in_morphisms with fHom330have rInM := hom.in_morphisms with rHom331have domF := hom.dom with fHom332have codF := hom.cod with fHom333have domR := hom.dom with rHom334have codR := hom.cod with rHom335have retraction : Retraction(C, f, r)336unfold Retraction337refine⟨fInM, rInM, ?_, ?_, ?_⟩338 . cc339 . cc340 . cc341exact SplitMonomorphism.of_retraction with retraction342343theorem Initial.split_epi (C i a f : Set)344requires category : Category(C)345requires initial : Initial(C, i)346requires aInO : a ∈ obj(C)347requires fHom : f ∈ hom(C, a, i)348shows SplitEpimorphism(C, f)349proof350obtain⟨s, sHom, unique⟩:= Initial.exists_morphism with initial, aInO351have fsHom := hom.comp with category, fHom, sHom352have fsId := Initial.endomorphism with category, initial, fsHom353have fInM := hom.in_morphisms with fHom354have sInM := hom.in_morphisms with sHom355have domF := hom.dom with fHom356have codF := hom.cod with fHom357have domS := hom.dom with sHom358have codS := hom.cod with sHom359havesection : SectionOf(C, f, s)360unfold SectionOf361refine⟨fInM, sInM, ?_, ?_, ?_⟩362 . cc363 . cc364 . cc365exact SplitEpimorphism.of_section withsection366367-- The unique morphism from an object to a terminal object, and from an368-- initial object to an object.369defunique terminalMorphism (C t a : Set)370 (f ∈ hom(C, a, t)) :=371∀ g ∈ hom(C, a, t), g = f372requires terminal : Terminal(C, t)373requires aInO : a ∈ obj(C)374proof375exact Terminal.exists_morphism with terminal, aInO376uniqueness377intros u hu first v hv second378exact second with u, hu379380theorem terminalMorphism.hom (C t a : Set)381requires terminal : Terminal(C, t)382requires aInO : a ∈ obj(C)383shows terminalMorphism(C, t, a) ∈ hom(C, a, t)384proof385have selected := terminalMorphism.selected at C, t, a with386 terminal, aInO387exact selected.left388389theorem terminalMorphism.eq (C t a g : Set)390requires terminal : Terminal(C, t)391requires aInO : a ∈ obj(C)392requires gHom : g ∈ hom(C, a, t)393shows g = terminalMorphism(C, t, a)394proof395have selected := terminalMorphism.selected at C, t, a with396 terminal, aInO397exact selected.right with g, gHom398399theorem terminalMorphism.self (C t : Set)400requires category : Category(C)401requires terminal : Terminal(C, t)402shows terminalMorphism(C, t, t) = id(C)(t)403proof404have tInO := Terminal.object with terminal405have idHom := hom.id with category, tInO406have equal := terminalMorphism.eq with terminal, tInO, idHom407 symm408exact equal409410theorem terminalMorphism.comp (C t a b f : Set)411requires category : Category(C)412requires terminal : Terminal(C, t)413requires aInO : a ∈ obj(C)414requires fHom : f ∈ hom(C, a, b)415shows terminalMorphism(C, t, b) ∘ f =416 terminalMorphism(C, t, a)417proof418have bInO : b ∈ obj(C)419have fInM := hom.in_morphisms with fHom420have codIn := Category.cod_closed with category, fInM421have codF := hom.cod with fHom422 rwa codF at codIn423have bHom := terminalMorphism.hom with terminal, bInO424have composite := hom.comp with category, bHom, fHom425exact terminalMorphism.eq with terminal, aInO, composite426427defunique initialMorphism (C i a : Set)428 (f ∈ hom(C, i, a)) :=429∀ g ∈ hom(C, i, a), g = f430requires initial : Initial(C, i)431requires aInO : a ∈ obj(C)432proof433exact Initial.exists_morphism with initial, aInO434uniqueness435intros u hu first v hv second436exact second with u, hu437438theorem initialMorphism.hom (C i a : Set)439requires initial : Initial(C, i)440requires aInO : a ∈ obj(C)441shows initialMorphism(C, i, a) ∈ hom(C, i, a)442proof443have selected := initialMorphism.selected at C, i, a with444 initial, aInO445exact selected.left446447theorem initialMorphism.eq (C i a g : Set)448requires initial : Initial(C, i)449requires aInO : a ∈ obj(C)450requires gHom : g ∈ hom(C, i, a)451shows g = initialMorphism(C, i, a)452proof453have selected := initialMorphism.selected at C, i, a with454 initial, aInO455exact selected.right with g, gHom456457theorem initialMorphism.self (C i : Set)458requires category : Category(C)459requires initial : Initial(C, i)460shows initialMorphism(C, i, i) = id(C)(i)461proof462have iInO := Initial.object with initial463have idHom := hom.id with category, iInO464have equal := initialMorphism.eq with initial, iInO, idHom465 symm466exact equal467468theorem initialMorphism.comp (C i a b f : Set)469requires category : Category(C)470requires initial : Initial(C, i)471requires bInO : b ∈ obj(C)472requires fHom : f ∈ hom(C, a, b)473shows f ∘ initialMorphism(C, i, a) =474 initialMorphism(C, i, b)475proof476have aInO : a ∈ obj(C)477have fInM := hom.in_morphisms with fHom478have domIn := Category.dom_closed with category, fInM479have domF := hom.dom with fHom480 rwa domF at domIn481have aHom := initialMorphism.hom with initial, aInO482have composite := hom.comp with category, fHom, aHom483exact initialMorphism.eq with initial, bInO, composite484485-- In a category with a zero object, each hom-set has a zero morphism.486theorem ZeroObject.zero_morphism (C z a b : Set)487requires category : Category(C)488requires zero : ZeroObject(C, z)489requires aInO : a ∈ obj(C)490requires bInO : b ∈ obj(C)491shows initialMorphism(C, z, b) ∘492 terminalMorphism(C, z, a) ∈ hom(C, a, b)493proof494have initial := ZeroObject.initial with zero495have terminal := ZeroObject.terminal with zero496have toZero := terminalMorphism.hom with terminal, aInO497have fromZero := initialMorphism.hom with initial, bInO498exact hom.comp with category, fromZero, toZero499