Other Agda modules in this section (28)
# Pullbacks as base changes of the diagonal
A cone to the product functor and the diagonal has two identifications
with a common target. Eliminating that target recovers the original cone.
Product uniqueness reconstructs the product-source identification from
the two recovered legs. The complete comparison retains both coordinate
squares and their normalized matching boundaries.
```agda
{-# OPTIONS --without-K #-}
module SCT.VolumeI.Chapter01.Section06.DiagonalPullbacks where
open import SCT.VolumeI.Chapter01.Section01.Vocabulary hiding (_=_)
import SCT.VolumeI.Chapter01.Section01.Terms as Terms
open Operations
open import SCT.VolumeI.Chapter01.Section02.Coherence
using (id₌; inv₌; comp-assoc; comp-unitˡ; module Composition; module Boundaries)
open Composition
open Boundaries using (SquareCell₌)
open import SCT.VolumeI.Chapter01.Section02.Products
open Calculus
open import SCT.VolumeI.Chapter01.Section02.Specialization
open import SCT.VolumeI.Chapter01.Section02.IdentificationSquares
open import SCT.VolumeI.Chapter01.Section03.ProductConstructions using (productMap)
open import SCT.VolumeI.Chapter01.Section03.Products.Pairing using (pair₌-extensionality)
open import SCT.VolumeI.Chapter01.Section03.Identifications.Inverses
open import SCT.VolumeI.Chapter01.Section03.Identifications.EndpointTransport
open import SCT.VolumeI.Chapter01.Section03.Identifications.Triangles
open import SCT.VolumeI.Chapter01.Section03.Identifications.TriangleCoherence
open import SCT.VolumeI.Chapter01.Section03.Identifications.FunctorCoherence
using (postWhisker-comp-One; postWhisker-id-One)
open import SCT.VolumeI.Chapter01.Section03.Equivalences
using (id-isEquiv; equiv-transport; equiv-compose; equiv-cancel-left)
open import SCT.VolumeI.Chapter01.Section06.Cones
open import SCT.VolumeI.Chapter01.Section06.ConeIdentifications
open import SCT.VolumeI.Chapter01.Section06.Pullbacks
open import SCT.VolumeI.Chapter01.Section06.PullbackSquares
module _ {Γ : Context} where
module DiagonalPullback {C D E : CAT Γ} (f : MAP C E) (g : MAP D E) where
F : MAP (C × D) (E × E)
F = productMap f g
Δ : MAP E (E × E)
Δ = pair (id E) (id E)
private
record CommonTarget (T : CAT Γ) : Set m where
open Terms.InContext T using (Term)
field
parameter : Term (C × D)
vertex : Term E
first : (f ∘ (pr₁ ∘ parameter)) =₁ vertex
second : (g ∘ (pr₂ ∘ parameter)) =₁ vertex
left₁ : {T : CAT Γ} (u : MAP T (C × D)) → (pr₁ ∘ (F ∘ u)) =₁ (f ∘ (pr₁ ∘ u))
left₁ u = comp-assoc u pr₁ f ∙ project-pair₁ (f ∘ pr₁) (g ∘ pr₂) u
left₂ : {T : CAT Γ} (u : MAP T (C × D)) → (pr₂ ∘ (F ∘ u)) =₁ (g ∘ (pr₂ ∘ u))
left₂ u = comp-assoc u pr₂ g ∙ project-pair₂ (f ∘ pr₁) (g ∘ pr₂) u
right₁ : {T : CAT Γ} (v : MAP T E) → (pr₁ ∘ (Δ ∘ v)) =₁ v
right₁ v = comp-unitˡ v ∙ project-pair₁ (id E) (id E) v
right₂ : {T : CAT Γ} (v : MAP T E) → (pr₂ ∘ (Δ ∘ v)) =₁ v
right₂ v = comp-unitˡ v ∙ project-pair₂ (id E) (id E) v
coordinates : {T : CAT Γ} → Cone F Δ T → CommonTarget T
coordinates s = record
{ parameter = Cone.left s; vertex = Cone.right s
; first = changeEndpoints (left₁ (Cone.left s)) (right₁ (Cone.right s)) (pr₁ ◁ Cone.match s)
; second = changeEndpoints (left₂ (Cone.left s)) (right₂ (Cone.right s)) (pr₂ ◁ Cone.match s) }
as-cone : {T : CAT Γ} → CommonTarget T → Cone F Δ T
as-cone d = record
{ left = parameter; right = vertex
; match = pair₌
((right₁ vertex) ⁻¹ ∙ (first ∙ left₁ parameter))
((right₂ vertex) ⁻¹ ∙ (second ∙ left₂ parameter)) }
where open CommonTarget d
first-computation : {T : CAT Γ} (d : CommonTarget T)
→ CommonTarget.first (coordinates (as-cone d)) =₂ CommonTarget.first d
first-computation d = cancel-endpoint-changes (left₁ parameter) (right₁ vertex) first ∙
comp₌-cong (id₌ (right₁ vertex))
(comp₌-cong (pair₌-β₁
((right₁ vertex) ⁻¹ ∙ (first ∙ left₁ parameter))
((right₂ vertex) ⁻¹ ∙ (second ∙ left₂ parameter)))
(id₌ ((left₁ parameter) ⁻¹)))
where open CommonTarget d
second-computation : {T : CAT Γ} (d : CommonTarget T)
→ CommonTarget.second (coordinates (as-cone d)) =₂ CommonTarget.second d
second-computation d = cancel-endpoint-changes (left₂ parameter) (right₂ vertex) second ∙
comp₌-cong (id₌ (right₂ vertex))
(comp₌-cong (pair₌-β₂
((right₁ vertex) ⁻¹ ∙ (first ∙ left₁ parameter))
((right₂ vertex) ⁻¹ ∙ (second ∙ left₂ parameter)))
(id₌ ((left₂ parameter) ⁻¹)))
where open CommonTarget d
recover : {T : CAT Γ} → CommonTarget T → Cone f g T
recover d = record
{ left = pr₁ ∘ parameter; right = pr₂ ∘ parameter; match = second ⁻¹ ∙ first }
where open CommonTarget d
recoverCone : {T : CAT Γ} → Cone F Δ T → Cone f g T
recoverCone s = recover (coordinates s)
```
## Comparing the coordinate descriptions
Two commuting squares preserve the quotient matching. Conversely, the two
legs of a recovered cone comparison determine the product-source comparison.
The second coordinate determines the common-target comparison by cancellation;
pasting then gives the first coordinate square.
```agda
record CommonTargetComparison {T : CAT Γ} (s t : CommonTarget T) : Set m where
field
parameter : CommonTarget.parameter s =₁ CommonTarget.parameter t
vertex : CommonTarget.vertex s =₁ CommonTarget.vertex t
first : SquareCell₌ (f ◁ (pr₁ ◁ parameter)) vertex
(CommonTarget.first s) (CommonTarget.first t)
second : SquareCell₌ (g ◁ (pr₂ ◁ parameter)) vertex
(CommonTarget.second s) (CommonTarget.second t)
left₁-natural : {T : CAT Γ} {u u′ : MAP T (C × D)} (L : u =₁ u′)
→ SquareCell₌ (pr₁ ◁ (F ◁ L)) (f ◁ (pr₁ ◁ L)) (left₁ u) (left₁ u′)
left₁-natural L = paste-square₌
(restrict-change-square-One pr₁ F (f ∘ pr₁) (pair-β₁ (f ∘ pr₁) (g ∘ pr₂)) L)
(postWhisker-comp-One L pr₁ f)
left₂-natural : {T : CAT Γ} {u u′ : MAP T (C × D)} (L : u =₁ u′)
→ SquareCell₌ (pr₂ ◁ (F ◁ L)) (g ◁ (pr₂ ◁ L)) (left₂ u) (left₂ u′)
left₂-natural L = paste-square₌
(restrict-change-square-One pr₂ F (g ∘ pr₂) (pair-β₂ (f ∘ pr₁) (g ∘ pr₂)) L)
(postWhisker-comp-One L pr₂ g)
right₁-natural : {T : CAT Γ} {v v′ : MAP T E} (R : v =₁ v′)
→ SquareCell₌ (pr₁ ◁ (Δ ◁ R)) R (right₁ v) (right₁ v′)
right₁-natural R = paste-square₌
(restrict-change-square-One pr₁ Δ (id E) (pair-β₁ (id E) (id E)) R)
(postWhisker-id-One R)
right₂-natural : {T : CAT Γ} {v v′ : MAP T E} (R : v =₁ v′)
→ SquareCell₌ (pr₂ ◁ (Δ ◁ R)) R (right₂ v) (right₂ v′)
right₂-natural R = paste-square₌
(restrict-change-square-One pr₂ Δ (id E) (pair-β₂ (id E) (id E)) R)
(postWhisker-id-One R)
coordinates-identification : {T : CAT Γ} {s t : Cone F Δ T}
→ ConeIdentification₁ s t → CommonTargetComparison (coordinates s) (coordinates t)
coordinates-identification {s = s} {t} Φ = record
{ parameter = L; vertex = R
; first = transport-square
(left₁ (Cone.left s)) (left₁ (Cone.left t))
(right₁ (Cone.right s)) (right₁ (Cone.right t))
(pr₁ ◁ Cone.match s) (pr₁ ◁ Cone.match t)
(pr₁ ◁ (F ◁ L)) (pr₁ ◁ (Δ ◁ R)) (f ◁ (pr₁ ◁ L)) R
(left₁-natural L) (right₁-natural R) (post-square₌ pr₁ (ConeIdentification₁.compatible Φ))
; second = transport-square
(left₂ (Cone.left s)) (left₂ (Cone.left t))
(right₂ (Cone.right s)) (right₂ (Cone.right t))
(pr₂ ◁ Cone.match s) (pr₂ ◁ Cone.match t)
(pr₂ ◁ (F ◁ L)) (pr₂ ◁ (Δ ◁ R)) (g ◁ (pr₂ ◁ L)) R
(left₂-natural L) (right₂-natural R) (post-square₌ pr₂ (ConeIdentification₁.compatible Φ)) }
where
L = ConeIdentification₁.left Φ
R = ConeIdentification₁.right Φ
coordinates-reflect : {T : CAT Γ} {s t : Cone F Δ T}
→ CommonTargetComparison (coordinates s) (coordinates t) → ConeIdentification₁ s t
coordinates-reflect {s = s} {t} Φ = record
{ left = parameter; right = vertex
; compatible = pair₌-extensionality
((postWhisker-comp₌ pr₁ (Δ ◁ vertex) (Cone.match s)) ⁻¹ ∙
(reflect-transported-square
(left₁ (Cone.left s)) (right₁ (Cone.right s))
(left₁ (Cone.left t)) (right₁ (Cone.right t))
(pr₁ ◁ Cone.match s) (pr₁ ◁ Cone.match t)
(pr₁ ◁ (F ◁ parameter)) (pr₁ ◁ (Δ ◁ vertex)) (f ◁ (pr₁ ◁ parameter)) vertex
(left₁-natural parameter) (right₁-natural vertex) first ∙
postWhisker-comp₌ pr₁ (Cone.match t) (F ◁ parameter)))
((postWhisker-comp₌ pr₂ (Δ ◁ vertex) (Cone.match s)) ⁻¹ ∙
(reflect-transported-square
(left₂ (Cone.left s)) (right₂ (Cone.right s))
(left₂ (Cone.left t)) (right₂ (Cone.right t))
(pr₂ ◁ Cone.match s) (pr₂ ◁ Cone.match t)
(pr₂ ◁ (F ◁ parameter)) (pr₂ ◁ (Δ ◁ vertex)) (g ◁ (pr₂ ◁ parameter)) vertex
(left₂-natural parameter) (right₂-natural vertex) second ∙
postWhisker-comp₌ pr₂ (Cone.match t) (F ◁ parameter))) }
where open CommonTargetComparison Φ
recover-identification : {T : CAT Γ} {s t : CommonTarget T}
→ CommonTargetComparison s t → ConeIdentification₁ (recover s) (recover t)
recover-identification Φ = record
{ left = pr₁ ◁ parameter; right = pr₂ ◁ parameter
; compatible = paste-square₌ first (inverse-square₌ second) }
where open CommonTargetComparison Φ
recover-reflect : {T : CAT Γ} {s t : CommonTarget T}
→ ConeIdentification₁ (recover s) (recover t) → CommonTargetComparison s t
recover-reflect {s = s} {t} Φ = record
{ parameter = L; vertex = R
; first = replace-edges₌ ((postWhisker f ◁ pair₌-β₁ l r) ⁻¹) (id₌ R) first-square
; second = replace-edges₌ ((postWhisker g ◁ pair₌-β₂ l r) ⁻¹) (id₌ R) second-square }
where
l : (pr₁ ∘ CommonTarget.parameter s) =₁ (pr₁ ∘ CommonTarget.parameter t)
l = ConeIdentification₁.left Φ
r : (pr₂ ∘ CommonTarget.parameter s) =₁ (pr₂ ∘ CommonTarget.parameter t)
r = ConeIdentification₁.right Φ
L : CommonTarget.parameter s =₁ CommonTarget.parameter t
L = pair₌ l r
R : CommonTarget.vertex s =₁ CommonTarget.vertex t
R = (CommonTarget.second t ∙ (g ◁ r)) ∙ (CommonTarget.second s) ⁻¹
second-square : SquareCell₌ (g ◁ r) R (CommonTarget.second s) (CommonTarget.second t)
second-square = (inv-comp-right (CommonTarget.second t ∙ (g ◁ r)) (CommonTarget.second s)) ⁻¹
first-square : SquareCell₌ (f ◁ l) R (CommonTarget.first s) (CommonTarget.first t)
first-square = replace-sides₌
(comp-inv-left (CommonTarget.second s) (CommonTarget.first s))
(comp-inv-left (CommonTarget.second t) (CommonTarget.first t))
(paste-square₌ (ConeIdentification₁.compatible Φ) second-square)
recoverCone-identification : {T : CAT Γ} {s t : Cone F Δ T}
→ ConeIdentification₁ s t → ConeIdentification₁ (recoverCone s) (recoverCone t)
recoverCone-identification Φ = recover-identification (coordinates-identification Φ)
recoverCone-reflect : {T : CAT Γ} {s t : Cone F Δ T}
→ ConeIdentification₁ (recoverCone s) (recoverCone t) → ConeIdentification₁ s t
recoverCone-reflect Φ = coordinates-reflect (recover-reflect Φ)
```
## The direct cone
The product-source leg pairs the original legs; the common target is the
second composite. Pairing the original matching with the identity, with
the two actual projection normalizations, gives the specified matching.
Its coordinate computations recover the whole original cone.
```agda
module Direct {T : CAT Γ} (s : Cone f g T) where
p : MAP T C
p = Cone.left s
q : MAP T D
q = Cone.right s
τ : (f ∘ p) =₁ (g ∘ q)
τ = Cone.match s
diagram : CommonTarget T
diagram = record
{ parameter = pair p q; vertex = g ∘ q
; first = τ ∙ (f ◁ pair-β₁ p q); second = g ◁ pair-β₂ p q }
value : Cone F Δ T
value = as-cone diagram
recover-law : ConeIdentification₁ (recoverCone value) s
recover-law = record
{ left = pair-β₁ p q; right = pair-β₂ p q
; compatible = (first-computation diagram ∙
(comp-inv-left (CommonTarget.second (coordinates value)) (CommonTarget.first (coordinates value)) ∙
comp₌-cong ((second-computation diagram) ⁻¹)
(id₌ (Cone.match (recoverCone value))))) ⁻¹ }
```
## Restriction of the recovered matching
Restrict each normalized coordinate along its actual associator boundary.
Pasting the two squares gives the quotient square; changing its endpoints
then recovers the full restricted matching. The product-source leg
comparisons are the inverse projection associators.
```agda
module CoordinateRestriction {S T A : CAT Γ}
(π : MAP (E × E) E) (j : MAP (C × D) A) (a : MAP A E)
(projection-law : (π ∘ F) =₁ (a ∘ j)) (diagonal-law : (π ∘ Δ) =₁ id E)
(s : Cone F Δ T) (r : MAP S T) where
u : MAP T (C × D)
u = Cone.left s
v : MAP T E
v = Cone.right s
left : {X : CAT Γ} (x : MAP X (C × D)) → (π ∘ (F ∘ x)) =₁ (a ∘ (j ∘ x))
left x = comp-assoc x j a ∙ restrict-triangle π F projection-law x
right : {X : CAT Γ} (y : MAP X E) → (π ∘ (Δ ∘ y)) =₁ y
right y = comp-unitˡ y ∙ restrict-triangle π Δ diagonal-law y
edge : {X : CAT Γ} (t : Cone F Δ X) → (a ∘ (j ∘ Cone.left t)) =₁ Cone.right t
edge t = changeEndpoints (left (Cone.left t)) (right (Cone.right t)) (π ◁ Cone.match t)
boundary : (a ∘ (j ∘ (u ∘ r))) =₁ ((a ∘ (j ∘ u)) ∘ r)
boundary = (comp-assoc r (j ∘ u) a) ⁻¹ ∙ (a ◁ (comp-assoc r u j) ⁻¹)
comparison : edge (cone-restrict r s) =₂ ((edge s ▷ r) ∙ boundary)
comparison = square-to-changeEndpoints (left (u ∘ r)) (right (v ∘ r))
(π ◁ Cone.match (cone-restrict r s)) ((edge s ▷ r) ∙ boundary)
((comp₌-assoc (edge s ▷ r) boundary (left (u ∘ r))) ⁻¹ ∙ extended)
where
original : SquareCell₌ (π ◁ (Cone.match s ▷ r)) (edge s ▷ r)
(restrict-triangle π (F ∘ u) (left u) r)
(restrict-triangle π (Δ ∘ v) (right v) r)
original = restrict-square-One π (Cone.match s) (edge s) (left u) (right v) r
(changeEndpoints-to-square (left u) (right v) (π ◁ Cone.match s) (edge s) (id₌ (edge s)))
extended : SquareCell₌ (π ◁ Cone.match (cone-restrict r s)) (edge s ▷ r)
(boundary ∙ left (u ∘ r)) (right (v ∘ r))
extended = replace-sides₌
(composite-normalization-pre π F j a projection-law u r)
(identity-normalization-pre π Δ diagonal-law v r)
(replace-edges₌
((postWhisker-changeEndpoints π (comp-assoc r u F) (comp-assoc r v Δ) (Cone.match s ▷ r)) ⁻¹)
(id₌ (edge s ▷ r))
(changeEndpoints-extend-square (π ◁ comp-assoc r u F) (π ◁ comp-assoc r v Δ)
(π ◁ (Cone.match s ▷ r)) original))
recover-pre : {S T : CAT Γ} (r : MAP S T) (s : Cone F Δ T)
→ ConeIdentification₁ (recoverCone (cone-restrict r s)) (cone-restrict r (recoverCone s))
recover-pre r s = record
{ left = l; right = q
; compatible = replace-sides₌ (id₌ restricted-matching)
(comp₌-cong (id₌ B) (comp₌-cong (matching-pre ⁻¹) (id₌ (A ⁻¹)))) normalized }
where
u = Cone.left s
v = Cone.right s
l : (pr₁ ∘ (u ∘ r)) =₁ ((pr₁ ∘ u) ∘ r)
l = (comp-assoc r u pr₁) ⁻¹
q : (pr₂ ∘ (u ∘ r)) =₁ ((pr₂ ∘ u) ∘ r)
q = (comp-assoc r u pr₂) ⁻¹
A = comp-assoc r (pr₁ ∘ u) f
B = comp-assoc r (pr₂ ∘ u) g
α = CommonTarget.first (coordinates s) ▷ r
β = CommonTarget.second (coordinates s) ▷ r
α′ = CommonTarget.first (coordinates (cone-restrict r s))
β′ = CommonTarget.second (coordinates (cone-restrict r s))
restricted-matching = β′ ⁻¹ ∙ α′
first : SquareCell₌ (A ⁻¹ ∙ (f ◁ l)) (id₌ (v ∘ r)) α′ α
first = (CoordinateRestriction.comparison pr₁ pr₁ f
(pair-β₁ (f ∘ pr₁) (g ∘ pr₂)) (pair-β₁ (id E) (id E)) s r ∙ comp₌-unitˡ-One α′) ⁻¹
second : SquareCell₌ (B ⁻¹ ∙ (g ◁ q)) (id₌ (v ∘ r)) β′ β
second = (CoordinateRestriction.comparison pr₂ pr₂ g
(pair-β₂ (f ∘ pr₁) (g ∘ pr₂)) (pair-β₂ (id E) (id E)) s r ∙ comp₌-unitˡ-One β′) ⁻¹
matching-pre : (Cone.match (recoverCone s) ▷ r) =₂ (β ⁻¹ ∙ α)
matching-pre = comp₌-cong (preWhisker-inverse (CommonTarget.second (coordinates s)) r) (id₌ α) ∙
preWhisker-comp₌ ((CommonTarget.second (coordinates s)) ⁻¹) (CommonTarget.first (coordinates s)) r
normalized : SquareCell₌ (f ◁ l) (g ◁ q) restricted-matching (changeEndpoints A B (β ⁻¹ ∙ α))
normalized = normalize-transported-square A B (β ⁻¹ ∙ α) restricted-matching (f ◁ l) (g ◁ q)
(paste-square₌ first (inverse-square₌ second))
recover-direct-pre : {S T : CAT Γ} (r : MAP S T) (s : Cone f g T)
→ ConeIdentification₁ (recoverCone (cone-restrict r (Direct.value s))) (cone-restrict r s)
recover-direct-pre r s = cone-compose
(cone-identification-restrict-One r (Direct.recover-law s)) (recover-pre r (Direct.value s))
```
## Universality and the specified equivalence
The inverse comparison factors the recovered chosen target through the
source universal cone. Recovery reflects its complete beta, and it
transfers endomorphism reflection in the same way. Recognition gives the
diagonal pullback property for every original universal cone.
```agda
source : Cone f g (Pullback f g)
source = pullback-cone f g
target : Cone F Δ (Pullback F Δ)
target = pullback-cone F Δ
module Universal {T : CAT Γ} (s : Cone f g T) (es : IsPullback s) where
private
module Original = UniversalCone s es
direct : Cone F Δ T
direct = Direct.value s
inverse : MAP (Pullback F Δ) T
inverse = Original.factor (recoverCone target)
factor-cone-law : ConeIdentification₁ (cone-restrict inverse direct) target
factor-cone-law = recoverCone-reflect
(cone-compose (Original.β (recoverCone target)) (recover-direct-pre inverse s))
reflect-identifications : (h k : MAP T T)
→ ConeIdentification₁ (cone-restrict h direct) (cone-restrict k direct) → h =₁ k
reflect-identifications h k Φ = Original.reflect h k
(cone-compose (recover-direct-pre k s)
(cone-compose (recoverCone-identification Φ) (cone-inverse (recover-direct-pre h s))))
isPullback : IsPullback direct
isPullback = isPullback-from-factor-and-reflection direct inverse factor-cone-law reflect-identifications
private
source-isPullback : IsPullback source
source-isPullback = equiv-transport
(pullback-reflect (id (Pullback f g)) (pullback-factor source)
(cone-compose (cone-inverse (pullback-factor-β source)) (cone-restrict-id source)))
(id-isEquiv (Pullback f g))
forward : MAP (Pullback f g) (Pullback F Δ)
forward = pullback-factor (Direct.value source)
forward-isEquiv : IsEquiv forward
forward-isEquiv = Universal.isPullback source source-isPullback
forward-left : (pullback₁ ∘ forward) =₁ pair (pullback₁ {f = f} {g}) pullback₂
forward-left = pullback-factor-β₁ (Direct.value source)
forward-right : (pullback₂ ∘ forward) =₁ (g ∘ pullback₂ {f = f} {g})
forward-right = pullback-factor-β₂ (Direct.value source)
```
## Arbitrary squares and their transported matching
The induced cone is identified with the actual direct value. Changing its
legs retains the full matching equation. Reflection of that complete cone
law compares their factors, proving preservation and reflection of the
pullback property in the original directions.
```agda
module Square {T : CAT Γ} (s : Cone f g T) where
value : Cone F Δ T
value = Direct.value s
left : MAP T (C × D)
left = Cone.left value
right : MAP T E
right = Cone.right value
induced : MAP T (Pullback F Δ)
induced = forward ∘ pullback-factor s
original : Cone F Δ T
original = cone-restrict induced target
source-cone-law : ConeIdentification₁ (cone-restrict (pullback-factor s) (Direct.value source)) value
source-cone-law = recoverCone-reflect
(cone-compose (cone-inverse (Direct.recover-law s))
(cone-compose (pullback-factor-β s) (recover-direct-pre (pullback-factor s) source)))
cone-law : ConeIdentification₁ original value
cone-law = cone-compose source-cone-law
(cone-compose (cone-identification-restrict-One (pullback-factor s) (pullback-factor-β (Direct.value source)))
(cone-inverse (cone-restrict-assoc (pullback-factor s) forward target)))
left-law : Cone.left original =₁ left
left-law = ConeIdentification₁.left cone-law
right-law : Cone.right original =₁ right
right-law = ConeIdentification₁.right cone-law
transported : Cone F Δ T
transported = record
{ left = left; right = right
; match = changeEndpoints (F ◁ left-law) (Δ ◁ right-law) (Cone.match original) }
matching-law : Cone.match transported =₂ Cone.match value
matching-law = square-to-changeEndpoints (F ◁ left-law) (Δ ◁ right-law)
(Cone.match original) (Cone.match value) (transpose-square₌ (ConeIdentification₁.compatible cone-law))
factor-law : pullback-factor value =₁ induced
factor-law = pullback-reflect _ _
(cone-compose (cone-inverse cone-law) (pullback-factor-β value))
preserve : IsPullback s → IsPullback value
preserve es = equiv-transport (factor-law ⁻¹) (equiv-compose (pullback-factor s) forward es forward-isEquiv)
reflect : IsPullback value → IsPullback s
reflect es = equiv-cancel-left (pullback-factor s) forward forward-isEquiv (equiv-transport factor-law es)
```