1-- Descent of functions through equivalence quotients, entirely in ZF.2-- 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.Relation.QuotientMap8import QuotientOperations910predicate Respects (f A r : Set) :=11∀ x ∈ A, ∀ y ∈ A, relates(r, x, y) → f(x) = f(y)1213defunique quotientMapValue (f A B r X : Set) (y ∈ B) :=14∃ x ∈ A, X = ⟦x⟧[A, r] ∧ y = f(x)15requires function : f : A → B16requires equivalence : Equivalence(A, r)17requires respects : Respects(f, A, r)18requires member : X ∈ (A ⧸ r)19proof20obtain⟨x, hx, shape⟩:= quotient.representative at A, r, X with member21have valueIn := FunctionBetween.apply_closed at f, A, B, x with*22refine⟨f(x), valueIn, x, hx, shape, rfl⟩23uniqueness24intros y hy py z hz pz25obtain⟨x, hx, sx, vx⟩:= py26obtain⟨u, hu, su, vu⟩:= pz27have equal : ⟦x⟧[A, r] = ⟦u⟧[A, r]28cc29have related := equivalenceClass.related_of_eq at A, r, x, u with*30unfold Respects at respects31have images := respects with x, hx, u, hu, related32cc3334defgraph quotientMap (f A B r : Set) (X ∈ (A ⧸ r)) : B := quotientMapValue(f, A, B, r, X)35requires function : f : A → B36requires equivalence : Equivalence(A, r)37requires respects : Respects(f, A, r)38proof39have selected := quotientMapValue.selected at f, A, B, r, X with*40exact selected.left4142theorem quotientMap.class (f A B r x : Set)43requires function : f : A → B44requires equivalence : Equivalence(A, r)45requires respects : Respects(f, A, r)46requires hx : x ∈ A47shows quotientMap(f, A, B, r)(⟦x⟧[A, r]) = f(x)48proof49have member := quotient.contains_class with*50have value := quotientMap.value at f, A, B, r, ⟦x⟧[A, r] with*51have selected := quotientMapValue.selected at f, A, B, r, ⟦x⟧[A, r] with*52obtain⟨u, hu, shape, output⟩:= selected.right53have related := equivalenceClass.related_of_eq with*54have images := respects with x, hx, u, hu, related55cc5657theorem quotientMap.injective (f A B r : Set)58requires function : f : A → B59requires equivalence : Equivalence(A, r)60requires respects : Respects(f, A, r)61requires reflects : ∀ x ∈ A, ∀ y ∈ A, f(x) = f(y) → relates(r, x, y)62shows InjectiveBetween(quotientMap(f, A, B, r), (A ⧸ r), B)63proof64have mapped := quotientMap.function at f, A, B, r with*65unfold InjectiveBetween66refine⟨mapped, ?_⟩67intros X hX Y hY z hz leftright68obtain⟨x, hx, sx⟩:= quotient.representative with hX69obtain⟨y, hy, sy⟩:= quotient.representative with hY70have vx := quotientMap.class with hx71have vy := quotientMap.class with hy72have ex := FunctionBetween.apply_value at quotientMap(f, A, B, r), (A ⧸ r), B, X, z with*73have ey := FunctionBetween.apply_value at quotientMap(f, A, B, r), (A ⧸ r), B, Y, z with*74have images : f(x) = f(y) bycc75have related := reflects with x, hx, y, hy, images76have classes := equivalenceClass.eq with*77cc7879theorem quotientMap.surjective (f A B r : Set)80requires function : f : A → B81requires equivalence : Equivalence(A, r)82requires respects : Respects(f, A, r)83requires onto : SurjectiveBetween(f, A, B)84shows SurjectiveBetween(quotientMap(f, A, B, r), (A ⧸ r), B)85proof86have mapped := quotientMap.function at f, A, B, r with*87unfold SurjectiveBetween88refine⟨mapped, ?_⟩89intros y hy90obtain⟨x, hx, edge⟩:= onto.right with y, hy91have member := quotient.contains_class with*92have value := quotientMap.class with*93have original := FunctionBetween.apply_value with*94have image := FunctionBetween.relates_apply at quotientMap(f, A, B, r), (A ⧸ r), B, ⟦x⟧[A, r] with*95refine⟨⟦x⟧[A, r], member, ?_⟩96cc9798-- The factorization equation determines the descended function uniquely.99theorem quotientMap.unique (f g A B r : Set)100requires function : f : A → B101requires equivalence : Equivalence(A, r)102requires respects : Respects(f, A, r)103requires candidate : g : (A ⧸ r) → B104requires factors : ∀ x ∈ A, g(⟦x⟧[A, r]) = f(x)105shows g = quotientMap(f, A, B, r)106proof107have mapped := quotientMap.function at f, A, B, r with*108apply FunctionBetween.ext with candidate, mapped109intros X hX110obtain⟨x, hx, shape⟩:= quotient.representative with hX111have given := factors with x, hx112have canonical := quotientMap.class with*113cc114115theorem quotientMap.factorization (f A B r : Set)116requires function : f : A → B117requires equivalence : Equivalence(A, r)118requires respects : Respects(f, A, r)119shows compose(quotientMap(f, A, B, r), quotientProjection(A, r), A, (A ⧸ r), B) = f120proof121have projection := quotientProjection.function at A, r with*122have mapped := quotientMap.function at f, A, B, r with*123have composed := compose.function at quotientMap(f, A, B, r), quotientProjection(A, r), A, (A ⧸ r), B with*124apply FunctionBetween.ext with composed, function125intros x hx126have composition := compose.apply at quotientMap(f, A, B, r), quotientProjection(A, r), A, (A ⧸ r), B, x with*127have projected := quotientProjection.value at A, r, x with*128have evaluated := quotientMap.class with*129cc130131theorem quotientMap.binary (f A B r op target X Y : Set)132requires function : f : A → B133requires equivalence : Equivalence(A, r)134requires respects : Respects(f, A, r)135requires closed : IsMagma(A, op)136requires compatible : CompatibleBinary(A, r, op)137requires preserves : ∀ x ∈ A, ∀ y ∈ A, f(op(x, y)) = target(f(x), f(y))138requires hX : X ∈ (A ⧸ r)139requires hY : Y ∈ (A ⧸ r)140shows quotientMap(f, A, B, r)((quotientBinary(A, r, op))(X, Y)) =141 target(quotientMap(f, A, B, r)(X), quotientMap(f, A, B, r)(Y))142proof143obtain⟨x, hx, sx⟩:= quotient.representative with hX144obtain⟨y, hy, sy⟩:= quotient.representative with hY145have operation := quotientBinary.classes at A, r, op, x, y with*146have output := quotientMap.class at f, A, B, r, op(x, y) with*147have vx := quotientMap.class at f, A, B, r, x with*148have vy := quotientMap.class at f, A, B, r, y with*149have original := preserves with x, hx, y, hy150cc151152theorem quotientMap.unary (f A B r op target X : Set)153requires function : f : A → B154requires equivalence : Equivalence(A, r)155requires respects : Respects(f, A, r)156requires closed : op : A → A157requires compatible : CompatibleUnary(A, r, op)158requires preserves : ∀ x ∈ A, f(op(x)) = target(f(x))159requires hX : X ∈ (A ⧸ r)160shows quotientMap(f, A, B, r)((quotientUnary(A, r, op))(X)) =161 target(quotientMap(f, A, B, r)(X))162proof163obtain⟨x, hx, sx⟩:= quotient.representative with hX164have operation := quotientUnary.classes at A, r, op, x with*165have outputIn : op(x) ∈ A166exact FunctionBetween.apply_closed at op, A, A, x with*167have output := quotientMap.class at f, A, B, r, op(x) with*168have vx := quotientMap.class at f, A, B, r, x with*169have original := preserves with x, hx170cc171