l3lab/ntp-mathlib huggingface dataset:
/--
The family of elements given by `x : FirstObj P S` is compatible iff `firstMap` and `secondMap`
map it to the same point.
-/
theorem compatible_iff (x : FirstObj P S) :
    ((firstObjEqFamily P S).hom x).Compatible ↔ firstMap P S x = secondMap P S x := by
  rw [Presieve.compatible_iff_sieveCompatible]
  constructor
  · intro t
    apply SecondObj.ext
    intros Y Z g f hf
    simpa [firstMap, secondMap] using t _ g hf
  · intro t Y Z f g hf
    rw [Types.limit_ext_iff'] at t
    

Proof state:
case mpr
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : FirstObj P S.arrows
t :
  ∀ (j : Discrete ((Y : C) × (Z : C) × (_ : Z ⟶ Y) × { f' // S.arrows f' })),
    limit.π (Discrete.functor fun f => P.obj (op f.snd.fst)) j (firstMap P S x) =
      limit.π (Discrete.functor fun f => P.obj (op f.snd.fst)) j (secondMap P S x)
Y Z : C
f : Y ⟶ X
g : Z ⟶ Y
hf : S.arrows f
⊢ (firstObjEqFamily P S.arrows).hom x (g ≫ f) (_ : S.arrows (g ≫ f)) =
    P.map g.op ((firstObjEqFamily P S.arrows).hom x f hf)

Next tactic:
simpa [firstMap, secondMap] using t ⟨⟨Y, Z, g, f, hf⟩⟩
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
⊢ Presieve.IsSheafFor P S.arrows ↔
    Nonempty
      (IsLimit
        (Fork.ofι (forkMap P S.arrows) (_ : forkMap P S.arrows ≫ firstMap P S = forkMap P S.arrows ≫ secondMap P S)))

Next tactic:
rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
⊢ Presieve.IsSheafFor P S.arrows ↔
    ∀ (x : Presieve.FamilyOfElements P S.arrows),
      firstMap P S ((firstObjEqFamily P S.arrows).symm x) = secondMap P S ((firstObjEqFamily P S.arrows).symm x) →
        ∃! x_1, forkMap P S.arrows x_1 = (firstObjEqFamily P S.arrows).symm x

Next tactic:
simp_rw [← compatible_iff]
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
⊢ Presieve.IsSheafFor P S.arrows ↔
    ∀ (x : Presieve.FamilyOfElements P S.arrows),
      Presieve.FamilyOfElements.Compatible ((firstObjEqFamily P S.arrows).hom ((firstObjEqFamily P S.arrows).symm x)) →
        ∃! x_1, forkMap P S.arrows x_1 = (firstObjEqFamily P S.arrows).symm x

Next tactic:
simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  

Proof state:
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
⊢ Presieve.IsSheafFor P S.arrows ↔
    ∀ (x : Presieve.FamilyOfElements P S.arrows),
      Presieve.FamilyOfElements.Compatible x → ∃! x_1, forkMap P S.arrows x_1 = (firstObjEqFamily P S.arrows).inv x

Next tactic:
apply ball_congr
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  

Proof state:
case H
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
⊢ ∀ (x : Presieve.FamilyOfElements P S.arrows),
    Presieve.FamilyOfElements.Compatible x →
      ((∃! t, Presieve.FamilyOfElements.IsAmalgamation x t) ↔
        ∃! x_1, forkMap P S.arrows x_1 = (firstObjEqFamily P S.arrows).inv x)

Next tactic:
intro x _
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  

Proof state:
case H
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
⊢ (∃! t, Presieve.FamilyOfElements.IsAmalgamation x t) ↔
    ∃! x_1, forkMap P S.arrows x_1 = (firstObjEqFamily P S.arrows).inv x

Next tactic:
apply exists_unique_congr
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  

Proof state:
case H.h
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
⊢ ∀ (a : P.obj (op X)),
    Presieve.FamilyOfElements.IsAmalgamation x a ↔ forkMap P S.arrows a = (firstObjEqFamily P S.arrows).inv x

Next tactic:
intro t
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  

Proof state:
case H.h
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
⊢ Presieve.FamilyOfElements.IsAmalgamation x t ↔ forkMap P S.arrows t = (firstObjEqFamily P S.arrows).inv x

Next tactic:
rw [← Iso.toEquiv_symm_fun]
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  

Proof state:
case H.h
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
⊢ Presieve.FamilyOfElements.IsAmalgamation x t ↔ forkMap P S.arrows t = (firstObjEqFamily P S.arrows).symm x

Next tactic:
rw [Equiv.eq_symm_apply]
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  rw [Equiv.eq_symm_apply]
  

Proof state:
case H.h
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
⊢ Presieve.FamilyOfElements.IsAmalgamation x t ↔ (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) = x

Next tactic:
constructor
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  rw [Equiv.eq_symm_apply]
  constructor
  · 

Proof state:
case H.h.mp
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
⊢ Presieve.FamilyOfElements.IsAmalgamation x t → (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) = x

Next tactic:
intro q
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  rw [Equiv.eq_symm_apply]
  constructor
  · intro q
    

Proof state:
case H.h.mp
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
q : Presieve.FamilyOfElements.IsAmalgamation x t
⊢ (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) = x

Next tactic:
funext Y f hf
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  rw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext Y f hf
    

Proof state:
case H.h.mp.h.h.h
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
q : Presieve.FamilyOfElements.IsAmalgamation x t
Y : C
f : Y ⟶ X
hf : S.arrows f
⊢ (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) f hf = x f hf

Next tactic:
simpa [firstObjEqFamily, forkMap] using q _ _
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  rw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext Y f hf
    simpa [firstObjEqFamily, forkMap] using q _ _
  · 

Proof state:
case H.h.mpr
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
⊢ (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) = x → Presieve.FamilyOfElements.IsAmalgamation x t

Next tactic:
intro q Y f hf
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  rw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext Y f hf
    simpa [firstObjEqFamily, forkMap] using q _ _
  · intro q Y f hf
    

Proof state:
case H.h.mpr
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
q : (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) = x
Y : C
f : Y ⟶ X
hf : S.arrows f
⊢ P.map f.op t = x f hf

Next tactic:
rw [← q]
/-- `P` is a sheaf for `S`, iff the fork given by `w` is an equalizer. -/
theorem equalizer_sheaf_condition :
    Presieve.IsSheafFor P (S : Presieve X) ↔ Nonempty (IsLimit (Fork.ofι _ (w P S))) := by
  rw [Types.type_equalizer_iff_unique,
    ← Equiv.forall_congr_left (firstObjEqFamily P (S : Presieve X)).toEquiv.symm]
  simp_rw [← compatible_iff]
  simp only [inv_hom_id_apply, Iso.toEquiv_symm_fun]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  rw [← Iso.toEquiv_symm_fun]
  rw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext Y f hf
    simpa [firstObjEqFamily, forkMap] using q _ _
  · intro q Y f hf
    rw [← q]
    

Proof state:
case H.h.mpr
C : Type u
inst✝ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
x : Presieve.FamilyOfElements P S.arrows
h✝ : Presieve.FamilyOfElements.Compatible x
t : P.obj (op X)
q : (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) = x
Y : C
f : Y ⟶ X
hf : S.arrows f
⊢ P.map f.op t = (firstObjEqFamily P S.arrows).toEquiv (forkMap P S.arrows t) f hf

Next tactic:
simp [firstObjEqFamily, forkMap]
theorem w : forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
⊢ forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R

Next tactic:
dsimp
theorem w : forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R := by
  dsimp
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
⊢ forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R

Next tactic:
ext fg
theorem w : forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R := by
  dsimp
  ext fg
  

Proof state:
case h.h
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
fg : ((Y : C) × { f // R f }) × (Z : C) × { g // R g }
a✝ : P.obj (op X)
⊢ ((forkMap P R ≫ firstMap P R) ≫ Pi.π (fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd))) fg) a✝ =
    ((forkMap P R ≫ secondMap P R) ≫ Pi.π (fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd))) fg) a✝

Next tactic:
simp only [firstMap, secondMap, forkMap]
theorem w : forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R := by
  dsimp
  ext fg
  simp only [firstMap, secondMap, forkMap]
  

Proof state:
case h.h
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
fg : ((Y : C) × { f // R f }) × (Z : C) × { g // R g }
a✝ : P.obj (op X)
⊢ (((Pi.lift fun f => P.map (↑f.snd).op) ≫
          Pi.lift fun fg => Pi.π (fun f => P.obj (op f.fst)) fg.1 ≫ P.map pullback.fst.op) ≫
        Pi.π (fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd))) fg)
      a✝ =
    (((Pi.lift fun f => P.map (↑f.snd).op) ≫
          Pi.lift fun fg => Pi.π (fun f => P.obj (op f.fst)) fg.2 ≫ P.map pullback.snd.op) ≫
        Pi.π (fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd))) fg)
      a✝

Next tactic:
simp only [limit.lift_π, limit.lift_π_assoc, assoc, Fan.mk_π_app]
theorem w : forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R := by
  dsimp
  ext fg
  simp only [firstMap, secondMap, forkMap]
  simp only [limit.lift_π, limit.lift_π_assoc, assoc, Fan.mk_π_app]
  

Proof state:
case h.h
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
fg : ((Y : C) × { f // R f }) × (Z : C) × { g // R g }
a✝ : P.obj (op X)
⊢ (P.map (↑fg.1.snd).op ≫ P.map pullback.fst.op) a✝ = (P.map (↑fg.2.snd).op ≫ P.map pullback.snd.op) a✝

Next tactic:
haveI := Presieve.hasPullbacks.has_pullbacks fg.1.2.2 fg.2.2.2
theorem w : forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R := by
  dsimp
  ext fg
  simp only [firstMap, secondMap, forkMap]
  simp only [limit.lift_π, limit.lift_π_assoc, assoc, Fan.mk_π_app]
  haveI := Presieve.hasPullbacks.has_pullbacks fg.1.2.2 fg.2.2.2
  

Proof state:
case h.h
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
fg : ((Y : C) × { f // R f }) × (Z : C) × { g // R g }
a✝ : P.obj (op X)
this : HasPullback ↑fg.1.snd ↑fg.2.snd
⊢ (P.map (↑fg.1.snd).op ≫ P.map pullback.fst.op) a✝ = (P.map (↑fg.2.snd).op ≫ P.map pullback.snd.op) a✝

Next tactic:
rw [← P.map_comp, ← op_comp, pullback.condition]
theorem w : forkMap P R ≫ firstMap P R = forkMap P R ≫ secondMap P R := by
  dsimp
  ext fg
  simp only [firstMap, secondMap, forkMap]
  simp only [limit.lift_π, limit.lift_π_assoc, assoc, Fan.mk_π_app]
  haveI := Presieve.hasPullbacks.has_pullbacks fg.1.2.2 fg.2.2.2
  rw [← P.map_comp, ← op_comp, pullback.condition]
  

Proof state:
case h.h
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
fg : ((Y : C) × { f // R f }) × (Z : C) × { g // R g }
a✝ : P.obj (op X)
this : HasPullback ↑fg.1.snd ↑fg.2.snd
⊢ P.map (pullback.snd ≫ ↑fg.2.snd).op a✝ = (P.map (↑fg.2.snd).op ≫ P.map pullback.snd.op) a✝

Next tactic:
simp
/--
The family of elements given by `x : FirstObj P S` is compatible iff `firstMap` and `secondMap`
map it to the same point.
-/
theorem compatible_iff (x : FirstObj P R) :
    ((firstObjEqFamily P R).hom x).Compatible ↔ firstMap P R x = secondMap P R x := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
x : FirstObj P R
⊢ Presieve.FamilyOfElements.Compatible ((firstObjEqFamily P R).hom x) ↔ firstMap P R x = secondMap P R x

Next tactic:
rw [Presieve.pullbackCompatible_iff]
/--
The family of elements given by `x : FirstObj P S` is compatible iff `firstMap` and `secondMap`
map it to the same point.
-/
theorem compatible_iff (x : FirstObj P R) :
    ((firstObjEqFamily P R).hom x).Compatible ↔ firstMap P R x = secondMap P R x := by
  rw [Presieve.pullbackCompatible_iff]
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
x : FirstObj P R
⊢ Presieve.FamilyOfElements.PullbackCompatible ((firstObjEqFamily P R).hom x) ↔ firstMap P R x = secondMap P R x

Next tactic:
constructor
/--
The family of elements given by `x : FirstObj P S` is compatible iff `firstMap` and `secondMap`
map it to the same point.
-/
theorem compatible_iff (x : FirstObj P R) :
    ((firstObjEqFamily P R).hom x).Compatible ↔ firstMap P R x = secondMap P R x := by
  rw [Presieve.pullbackCompatible_iff]
  constructor
  · 

Proof state:
case mp
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
x : FirstObj P R
⊢ Presieve.FamilyOfElements.PullbackCompatible ((firstObjEqFamily P R).hom x) → firstMap P R x = secondMap P R x

Next tactic:
intro t
/--
The family of elements given by `x : FirstObj P S` is compatible iff `firstMap` and `secondMap`
map it to the same point.
-/
theorem compatible_iff (x : FirstObj P R) :
    ((firstObjEqFamily P R).hom x).Compatible ↔ firstMap P R x = secondMap P R x := by
  rw [Presieve.pullbackCompatible_iff]
  constructor
  · intro t
    

Proof state:
case mp
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
x : FirstObj P R
t : Presieve.FamilyOfElements.PullbackCompatible ((firstObjEqFamily P R).hom x)
⊢ firstMap P R x = secondMap P R x

Next tactic:
apply Limits.Types.limit_ext
/--
The family of elements given by `x : FirstObj P S` is compatible iff `firstMap` and `secondMap`
map it to the same point.
-/
theorem compatible_iff (x : FirstObj P R) :
    ((firstObjEqFamily P R).hom x).Compatible ↔ firstMap P R x = secondMap P R x := by
  rw [Presieve.pullbackCompatible_iff]
  constructor
  · intro t
    apply Limits.Types.limit_ext
    

Proof state:
case mp.w
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
x : FirstObj P R
t : Presieve.FamilyOfElements.PullbackCompatible ((firstObjEqFamily P R).hom x)
⊢ ∀ (j : Discrete (((Y : C) × { f // R f }) × (Z : C) × { g // R g })),
    limit.π (Discrete.functor fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd))) j (firstMap P R x) =
      limit.π (Discrete.functor fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd))) j (secondMap P R x)

Next tactic:
rintro ⟨⟨Y, f, hf⟩, Z, g, hg⟩
/--
The family of elements given by `x : FirstObj P S` is compatible iff `firstMap` and `secondMap`
map it to the same point.
-/
theorem compatible_iff (x : FirstObj P R) :
    ((firstObjEqFamily P R).hom x).Compatible ↔ firstMap P R x = secondMap P R x := by
  rw [Presieve.pullbackCompatible_iff]
  constructor
  · intro t
    apply Limits.Types.limit_ext
    rintro ⟨⟨Y, f, hf⟩, Z, g, hg⟩
    

Proof state:
case mp.w.mk.mk.mk.mk.mk.mk
C : Type u
inst✝¹ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X : C
R : Presieve X
S : Sieve X
inst✝ : Presieve.hasPullbacks R
x : FirstObj P R
t : Presieve.FamilyOfElements.PullbackCompatible ((firstObjEqFamily P R).hom x)
Y : C
f : Y ⟶ X
hf : R f
Z : C
g : Z ⟶ X
hg : R g
⊢ limit.π (Discrete.functor fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd)))
      { as := ({ fst := Y, snd := { val := f, property := hf } }, { fst := Z, snd := { val := g, property := hg } }) }
      (firstMap P R x) =
    limit.π (Discrete.functor fun fg => P.obj (op (Limits.pullback ↑fg.1.snd ↑fg.2.snd)))
      { as := ({ fst := Y, snd := { val := f, property := hf } }, { fst := Z, snd := { val := g, property := hg } }) }
      (secondMap P R x)

Next tactic:
simpa [firstMap, secondMap] using t hf hg