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 X) : (Arrows.Compatible P π ((Types.productIso _).hom x)) ↔
    firstMap P X π x = secondMap P X π x := by
  rw [Arrows.pullbackCompatible_iff]
  constructor
  · intro t
    ext ij
    

Proof state:
case mp.h
C : Type u
inst✝³ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X✝ : C
R : Presieve X✝
S : Sieve X✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : FirstObj P X
t : Arrows.PullbackCompatible P π ((Types.productIso fun i => P.obj (op (X i))).hom x)
ij : I × I
⊢ Pi.π (fun ij => P.obj (op (Limits.pullback (π ij.1) (π ij.2)))) ij (firstMap P X π x) =
    Pi.π (fun ij => P.obj (op (Limits.pullback (π ij.1) (π ij.2)))) ij (secondMap P X π x)

Next tactic:
simpa [firstMap, secondMap] using t ij.1 ij.2
/--
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 X) : (Arrows.Compatible P π ((Types.productIso _).hom x)) ↔
    firstMap P X π x = secondMap P X π x := by
  rw [Arrows.pullbackCompatible_iff]
  constructor
  · intro t
    ext ij
    simpa [firstMap, secondMap] using t ij.1 ij.2
  · 

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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : FirstObj P X
⊢ firstMap P X π x = secondMap P X π x →
    Arrows.PullbackCompatible P π ((Types.productIso fun i => P.obj (op (X i))).hom x)

Next tactic:
intro t i j
/--
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 X) : (Arrows.Compatible P π ((Types.productIso _).hom x)) ↔
    firstMap P X π x = secondMap P X π x := by
  rw [Arrows.pullbackCompatible_iff]
  constructor
  · intro t
    ext ij
    simpa [firstMap, secondMap] using t ij.1 ij.2
  · intro t i j
    

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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : FirstObj P X
t : firstMap P X π x = secondMap P X π x
i j : I
⊢ P.map pullback.fst.op ((Types.productIso fun i => P.obj (op (X i))).hom x i) =
    P.map pullback.snd.op ((Types.productIso fun i => P.obj (op (X i))).hom x j)

Next tactic:
apply_fun Pi.π (fun (ij : I × I) ↦ P.obj (op (pullback (π ij.1) (π ij.2)))) ⟨i, j⟩ at 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 X) : (Arrows.Compatible P π ((Types.productIso _).hom x)) ↔
    firstMap P X π x = secondMap P X π x := by
  rw [Arrows.pullbackCompatible_iff]
  constructor
  · intro t
    ext ij
    simpa [firstMap, secondMap] using t ij.1 ij.2
  · intro t i j
    apply_fun Pi.π (fun (ij : I × I) ↦ P.obj (op (pullback (π ij.1) (π ij.2)))) ⟨i, j⟩ 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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : FirstObj P X
i j : I
t :
  Pi.π (fun ij => P.obj (op (Limits.pullback (π ij.1) (π ij.2)))) (i, j) (firstMap P X π x) =
    Pi.π (fun ij => P.obj (op (Limits.pullback (π ij.1) (π ij.2)))) (i, j) (secondMap P X π x)
⊢ P.map pullback.fst.op ((Types.productIso fun i => P.obj (op (X i))).hom x i) =
    P.map pullback.snd.op ((Types.productIso fun i => P.obj (op (X i))).hom x j)

Next tactic:
simpa [firstMap, secondMap] using t
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P 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✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
⊢ IsSheafFor P (ofArrows X π) ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (_ : forkMap P X π ≫ firstMap P X π = forkMap P X π ≫ secondMap P X π)))

Next tactic:
rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_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✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
⊢ (∀ (x : (i : I) → P.obj (op (X i))), Arrows.Compatible P π x → ∃! t, ∀ (i : I), P.map (π i).op t = x i) ↔
    ∀ (y : FirstObj P X), firstMap P X π y = secondMap P X π y → ∃! x, forkMap P X π x = y

Next tactic:
erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
⊢ (∀ (x : (i : I) → P.obj (op (X i))), Arrows.Compatible P π x → ∃! t, ∀ (i : I), P.map (π i).op t = x i) ↔
    ∀ (x : (j : I) → P.obj (op (X j))),
      firstMap P X π ((Types.productIso fun i => P.obj (op (X i))).symm x) =
          secondMap P X π ((Types.productIso fun i => P.obj (op (X i))).symm x) →
        ∃! x_1, forkMap P X π x_1 = (Types.productIso fun i => P.obj (op (X i))).symm x

Next tactic:
simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  

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✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
⊢ (∀ (x : (i : I) → P.obj (op (X i))), Arrows.Compatible P π x → ∃! t, ∀ (i : I), P.map (π i).op t = x i) ↔
    ∀ (x : (j : I) → P.obj (op (X j))),
      Arrows.Compatible P π x → ∃! x_1, forkMap P X π x_1 = (Types.productIso fun i => P.obj (op (X i))).symm x

Next tactic:
apply ball_congr
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
⊢ ∀ (x : (i : I) → P.obj (op (X i))),
    Arrows.Compatible P π x →
      ((∃! t, ∀ (i : I), P.map (π i).op t = x i) ↔
        ∃! x_1, forkMap P X π x_1 = (Types.productIso fun i => P.obj (op (X i))).symm x)

Next tactic:
intro x _
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
⊢ (∃! t, ∀ (i : I), P.map (π i).op t = x i) ↔
    ∃! x_1, forkMap P X π x_1 = (Types.productIso fun i => P.obj (op (X i))).symm x

Next tactic:
apply exists_unique_congr
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
⊢ ∀ (a : P.obj (op B)),
    (∀ (i : I), P.map (π i).op a = x i) ↔ forkMap P X π a = (Types.productIso fun i => P.obj (op (X i))).symm x

Next tactic:
intro t
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
⊢ (∀ (i : I), P.map (π i).op t = x i) ↔ forkMap P X π t = (Types.productIso fun i => P.obj (op (X i))).symm x

Next tactic:
erw [Equiv.eq_symm_apply]
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  erw [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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
⊢ (∀ (i : I), P.map (π i).op t = x i) ↔ (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) = x

Next tactic:
constructor
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  erw [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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
⊢ (∀ (i : I), P.map (π i).op t = x i) → (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) = x

Next tactic:
intro q
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  erw [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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
q : ∀ (i : I), P.map (π i).op t = x i
⊢ (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) = x

Next tactic:
funext i
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  erw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext i
    

Proof state:
case H.h.mp.h
C : Type u
inst✝³ : Category.{v, u} C
P : Cᵒᵖ ⥤ Type (max v u)
X✝ : C
R : Presieve X✝
S : Sieve X✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
q : ∀ (i : I), P.map (π i).op t = x i
i : I
⊢ (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) i = x i

Next tactic:
simpa [forkMap] using q i
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  erw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext i
    simpa [forkMap] using q i
  · 

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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
⊢ (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) = x → ∀ (i : I), P.map (π i).op t = x i

Next tactic:
intro q i
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  erw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext i
    simpa [forkMap] using q i
  · intro q i
    

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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
q : (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) = x
i : I
⊢ P.map (π i).op t = x i

Next tactic:
rw [← q]
/--
`P` is a sheaf for `Presieve.ofArrows X π`, iff the fork given by `w` is an equalizer.
See <https://stacks.math.columbia.edu/tag/00VM>.
-/
theorem sheaf_condition : (ofArrows X π).IsSheafFor P ↔
    Nonempty (IsLimit (Fork.ofι (forkMap P X π) (w P X π))) := by
  rw [Types.type_equalizer_iff_unique, isSheafFor_arrows_iff]
  erw [← Equiv.forall_congr_left (Types.productIso _).toEquiv.symm]
  simp_rw [← compatible_iff, ← Iso.toEquiv_fun, Equiv.apply_symm_apply]
  apply ball_congr
  intro x _
  apply exists_unique_congr
  intro t
  erw [Equiv.eq_symm_apply]
  constructor
  · intro q
    funext i
    simpa [forkMap] using q i
  · intro q i
    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✝
inst✝² : hasPullbacks R
B : C
I : Type
X : I → C
π : (i : I) → X i ⟶ B
inst✝¹ : UnivLE.{w, max v u}
inst✝ : hasPullbacks (ofArrows X π)
x : (i : I) → P.obj (op (X i))
h✝ : Arrows.Compatible P π x
t : P.obj (op B)
q : (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) = x
i : I
⊢ P.map (π i).op t = (Types.productIso fun i => P.obj (op (X i))).toEquiv (forkMap P X π t) i

Next tactic:
simp [forkMap]
theorem continuantsAux_stable_step_of_terminated (terminated_at_n : g.TerminatedAt n) :
    g.continuantsAux (n + 2) = g.continuantsAux (n + 1) := by
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
terminated_at_n : TerminatedAt g n
⊢ continuantsAux g (n + 2) = continuantsAux g (n + 1)

Next tactic:
rw [terminatedAt_iff_s_none] at terminated_at_n
theorem continuantsAux_stable_step_of_terminated (terminated_at_n : g.TerminatedAt n) :
    g.continuantsAux (n + 2) = g.continuantsAux (n + 1) := by
  rw [terminatedAt_iff_s_none] at terminated_at_n
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
terminated_at_n : Stream'.Seq.get? g.s n = none
⊢ continuantsAux g (n + 2) = continuantsAux g (n + 1)

Next tactic:
simp only [continuantsAux, Nat.add_eq, add_zero, terminated_at_n]
theorem continuantsAux_stable_of_terminated (n_lt_m : n < m) (terminated_at_n : g.TerminatedAt n) :
    g.continuantsAux m = g.continuantsAux (n + 1) := by
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
n_lt_m : n < m
terminated_at_n : TerminatedAt g n
⊢ continuantsAux g m = continuantsAux g (n + 1)

Next tactic:
refine' Nat.le_induction rfl (fun k hnk hk => _) _ n_lt_m
theorem continuantsAux_stable_of_terminated (n_lt_m : n < m) (terminated_at_n : g.TerminatedAt n) :
    g.continuantsAux m = g.continuantsAux (n + 1) := by
  refine' Nat.le_induction rfl (fun k hnk hk => _) _ n_lt_m
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
n_lt_m : n < m
terminated_at_n : TerminatedAt g n
k : ℕ
hnk : Nat.succ n ≤ k
hk : continuantsAux g k = continuantsAux g (n + 1)
⊢ continuantsAux g (k + 1) = continuantsAux g (n + 1)

Next tactic:
rcases Nat.exists_eq_add_of_lt hnk with ⟨k, rfl⟩
theorem continuantsAux_stable_of_terminated (n_lt_m : n < m) (terminated_at_n : g.TerminatedAt n) :
    g.continuantsAux m = g.continuantsAux (n + 1) := by
  refine' Nat.le_induction rfl (fun k hnk hk => _) _ n_lt_m
  rcases Nat.exists_eq_add_of_lt hnk with ⟨k, rfl⟩
  

Proof state:
case intro
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
n_lt_m : n < m
terminated_at_n : TerminatedAt g n
k : ℕ
hnk : Nat.succ n ≤ n + k + 1
hk : continuantsAux g (n + k + 1) = continuantsAux g (n + 1)
⊢ continuantsAux g (n + k + 1 + 1) = continuantsAux g (n + 1)

Next tactic:
refine' (continuantsAux_stable_step_of_terminated _).trans hk
theorem continuantsAux_stable_of_terminated (n_lt_m : n < m) (terminated_at_n : g.TerminatedAt n) :
    g.continuantsAux m = g.continuantsAux (n + 1) := by
  refine' Nat.le_induction rfl (fun k hnk hk => _) _ n_lt_m
  rcases Nat.exists_eq_add_of_lt hnk with ⟨k, rfl⟩
  refine' (continuantsAux_stable_step_of_terminated _).trans hk
  

Proof state:
case intro
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
n_lt_m : n < m
terminated_at_n : TerminatedAt g n
k : ℕ
hnk : Nat.succ n ≤ n + k + 1
hk : continuantsAux g (n + k + 1) = continuantsAux g (n + 1)
⊢ TerminatedAt g (n + k)

Next tactic:
exact terminated_stable (Nat.le_add_right _ _) terminated_at_n
theorem convergents'Aux_stable_step_of_terminated {s : Stream'.Seq <| Pair K}
    (terminated_at_n : s.TerminatedAt n) : convergents'Aux s (n + 1) = convergents'Aux s n := by
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
s : Stream'.Seq (Pair K)
terminated_at_n : Stream'.Seq.TerminatedAt s n
⊢ convergents'Aux s (n + 1) = convergents'Aux s n

Next tactic:
change s.get? n = none at terminated_at_n
theorem convergents'Aux_stable_step_of_terminated {s : Stream'.Seq <| Pair K}
    (terminated_at_n : s.TerminatedAt n) : convergents'Aux s (n + 1) = convergents'Aux s n := by
  change s.get? n = none at terminated_at_n
  

Proof state:
K : Type u_1
g : GeneralizedContinuedFraction K
n m : ℕ
inst✝ : DivisionRing K
s : Stream'.Seq (Pair K)
terminated_at_n : Stream'.Seq.get? s n = none
⊢ convergents'Aux s (n + 1) = convergents'Aux s n

Next tactic:
induction' n with n IH generalizing s