l3lab/ntp-mathlib huggingface dataset:
/-- We can partition the square `s ×ˢ s` into shifted diagonals as such:
```
01234
40123
34012
23401
12340
```

The diagonals are given by the cycle `f`.
-/
theorem _root_.Finset.product_self_eq_disjiUnion_perm (hf : f.IsCycleOn s) :
    s ×ˢ s =
      (range s.card).disjiUnion
        (fun k => s.map ⟨fun i => (i, (f ^ k) i), fun i j => congr_arg Prod.fst⟩)
        (product_self_eq_disjiUnion_perm_aux hf) := by
  ext ⟨a, b⟩
  simp only [mem_product, Equiv.Perm.coe_pow, mem_disjiUnion, mem_range, mem_map,
    Function.Embedding.coeFn_mk, Prod.mk.inj_iff, exists_prop]
  refine' ⟨fun hx => _, _⟩
  · obtain ⟨n, hn, rfl⟩ := hf.exists_pow_eq hx.1 hx.2
    

Proof state:
case a.mk.refine'_1.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝ : DecidableEq α
f : Perm α
s : Finset α
hf : IsCycleOn f ↑s
a : α
n : ℕ
hn : n < card s
hx : a ∈ s ∧ (f ^ n) a ∈ s
⊢ ∃ a_1 < card s, ∃ a_2 ∈ s, a_2 = a ∧ (⇑f)^[a_1] a_2 = (f ^ n) a

Next tactic:
exact ⟨n, hn, a, hx.1, rfl, by rw [f.iterate_eq_pow]⟩
/-- We can partition the square `s ×ˢ s` into shifted diagonals as such:
```
01234
40123
34012
23401
12340
```

The diagonals are given by the cycle `f`.
-/
theorem _root_.Finset.product_self_eq_disjiUnion_perm (hf : f.IsCycleOn s) :
    s ×ˢ s =
      (range s.card).disjiUnion
        (fun k => s.map ⟨fun i => (i, (f ^ k) i), fun i j => congr_arg Prod.fst⟩)
        (product_self_eq_disjiUnion_perm_aux hf) := by
  ext ⟨a, b⟩
  simp only [mem_product, Equiv.Perm.coe_pow, mem_disjiUnion, mem_range, mem_map,
    Function.Embedding.coeFn_mk, Prod.mk.inj_iff, exists_prop]
  refine' ⟨fun hx => _, _⟩
  · obtain ⟨n, hn, rfl⟩ := hf.exists_pow_eq hx.1 hx.2
    exact ⟨n, hn, a, hx.1, rfl, by 

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝ : DecidableEq α
f : Perm α
s : Finset α
hf : IsCycleOn f ↑s
a : α
n : ℕ
hn : n < card s
hx : a ∈ s ∧ (f ^ n) a ∈ s
⊢ (⇑f)^[n] a = (f ^ n) a

Next tactic:
rw [f.iterate_eq_pow]
/-- We can partition the square `s ×ˢ s` into shifted diagonals as such:
```
01234
40123
34012
23401
12340
```

The diagonals are given by the cycle `f`.
-/
theorem _root_.Finset.product_self_eq_disjiUnion_perm (hf : f.IsCycleOn s) :
    s ×ˢ s =
      (range s.card).disjiUnion
        (fun k => s.map ⟨fun i => (i, (f ^ k) i), fun i j => congr_arg Prod.fst⟩)
        (product_self_eq_disjiUnion_perm_aux hf) := by
  ext ⟨a, b⟩
  simp only [mem_product, Equiv.Perm.coe_pow, mem_disjiUnion, mem_range, mem_map,
    Function.Embedding.coeFn_mk, Prod.mk.inj_iff, exists_prop]
  refine' ⟨fun hx => _, _⟩
  · obtain ⟨n, hn, rfl⟩ := hf.exists_pow_eq hx.1 hx.2
    exact ⟨n, hn, a, hx.1, rfl, by rw [f.iterate_eq_pow]⟩
  · 

Proof state:
case a.mk.refine'_2
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝ : DecidableEq α
f : Perm α
s : Finset α
hf : IsCycleOn f ↑s
a b : α
⊢ (∃ a_1 < card s, ∃ a_2 ∈ s, a_2 = a ∧ (⇑f)^[a_1] a_2 = b) → a ∈ s ∧ b ∈ s

Next tactic:
rintro ⟨n, -, a, ha, rfl, rfl⟩
/-- We can partition the square `s ×ˢ s` into shifted diagonals as such:
```
01234
40123
34012
23401
12340
```

The diagonals are given by the cycle `f`.
-/
theorem _root_.Finset.product_self_eq_disjiUnion_perm (hf : f.IsCycleOn s) :
    s ×ˢ s =
      (range s.card).disjiUnion
        (fun k => s.map ⟨fun i => (i, (f ^ k) i), fun i j => congr_arg Prod.fst⟩)
        (product_self_eq_disjiUnion_perm_aux hf) := by
  ext ⟨a, b⟩
  simp only [mem_product, Equiv.Perm.coe_pow, mem_disjiUnion, mem_range, mem_map,
    Function.Embedding.coeFn_mk, Prod.mk.inj_iff, exists_prop]
  refine' ⟨fun hx => _, _⟩
  · obtain ⟨n, hn, rfl⟩ := hf.exists_pow_eq hx.1 hx.2
    exact ⟨n, hn, a, hx.1, rfl, by rw [f.iterate_eq_pow]⟩
  · rintro ⟨n, -, a, ha, rfl, rfl⟩
    

Proof state:
case a.mk.refine'_2.intro.intro.intro.intro.intro
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝ : DecidableEq α
f : Perm α
s : Finset α
hf : IsCycleOn f ↑s
n : ℕ
a : α
ha : a ∈ s
⊢ a ∈ s ∧ (⇑f)^[n] a ∈ s

Next tactic:
exact ⟨ha, (hf.1.iterate _).mapsTo ha⟩
theorem _root_.Finset.sum_smul_sum_eq_sum_perm (hσ : σ.IsCycleOn s) (f : ι → α) (g : ι → β) :
    ((∑ i in s, f i) • ∑ i in s, g i) = ∑ k in range s.card, ∑ i in s, f i • g ((σ ^ k) i) := by
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝³ : DecidableEq α
inst✝² : Semiring α
inst✝¹ : AddCommMonoid β
inst✝ : Module α β
s : Finset ι
σ : Perm ι
hσ : IsCycleOn σ ↑s
f : ι → α
g : ι → β
⊢ (∑ i in s, f i) • ∑ i in s, g i = ∑ k in range (card s), ∑ i in s, f i • g ((σ ^ k) i)

Next tactic:
simp_rw [sum_smul_sum, product_self_eq_disjiUnion_perm hσ, sum_disjiUnion, sum_map]
theorem _root_.Finset.sum_smul_sum_eq_sum_perm (hσ : σ.IsCycleOn s) (f : ι → α) (g : ι → β) :
    ((∑ i in s, f i) • ∑ i in s, g i) = ∑ k in range s.card, ∑ i in s, f i • g ((σ ^ k) i) := by
  simp_rw [sum_smul_sum, product_self_eq_disjiUnion_perm hσ, sum_disjiUnion, sum_map]
  

Proof state:
ι : Type u_1
α : Type u_2
β : Type u_3
inst✝³ : DecidableEq α
inst✝² : Semiring α
inst✝¹ : AddCommMonoid β
inst✝ : Module α β
s : Finset ι
σ : Perm ι
hσ : IsCycleOn σ ↑s
f : ι → α
g : ι → β
⊢ ∑ x in range (card s),
      ∑ x_1 in s,
        f
            ({ toFun := fun i => (i, (σ ^ x) i),
                  inj' :=
                    (_ :
                      ∀ (i j : ι),
                        (fun i => (i, (σ ^ x) i)) i = (fun i => (i, (σ ^ x) i)) j →
                          ((fun i => (i, (σ ^ x) i)) i).1 = ((fun i => (i, (σ ^ x) i)) j).1) }
                x_1).1 •
          g
            ({ toFun := fun i => (i, (σ ^ x) i),
                  inj' :=
                    (_ :
                      ∀ (i j : ι),
                        (fun i => (i, (σ ^ x) i)) i = (fun i => (i, (σ ^ x) i)) j →
                          ((fun i => (i, (σ ^ x) i)) i).1 = ((fun i => (i, (σ ^ x) i)) j).1) }
                x_1).2 =
    ∑ k in range (card s), ∑ i in s, f i • g ((σ ^ k) i)

Next tactic:
rfl
/-- Given a compatible family of sections over open sets, extend it to a
  section of the functor `(Pairwise.diagram U).op ⋙ F`. -/
def IsCompatible.sectionPairwise {sf} (h : IsCompatible F U sf) :
    ((Pairwise.diagram U).op ⋙ F).sections := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
h : IsCompatible F U sf
⊢ ↑(Functor.sections ((Pairwise.diagram U).op ⋙ F))

Next tactic:
refine ⟨objPairwiseOfFamily sf, ?_⟩
/-- Given a compatible family of sections over open sets, extend it to a
  section of the functor `(Pairwise.diagram U).op ⋙ F`. -/
def IsCompatible.sectionPairwise {sf} (h : IsCompatible F U sf) :
    ((Pairwise.diagram U).op ⋙ F).sections := by
  refine ⟨objPairwiseOfFamily sf, ?_⟩
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
h : IsCompatible F U sf
⊢ objPairwiseOfFamily sf ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F)

Next tactic:
let G := (Pairwise.diagram U).op ⋙ F
/-- Given a compatible family of sections over open sets, extend it to a
  section of the functor `(Pairwise.diagram U).op ⋙ F`. -/
def IsCompatible.sectionPairwise {sf} (h : IsCompatible F U sf) :
    ((Pairwise.diagram U).op ⋙ F).sections := by
  refine ⟨objPairwiseOfFamily sf, ?_⟩
  let G := (Pairwise.diagram U).op ⋙ F
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
h : IsCompatible F U sf
G : (CategoryTheory.Pairwise ι)ᵒᵖ ⥤ Type u := (Pairwise.diagram U).op ⋙ F
⊢ objPairwiseOfFamily sf ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F)

Next tactic:
rintro (i|⟨i,j⟩) (i'|⟨i',j'⟩) (_|_|_|_)
/-- Given a compatible family of sections over open sets, extend it to a
  section of the functor `(Pairwise.diagram U).op ⋙ F`. -/
def IsCompatible.sectionPairwise {sf} (h : IsCompatible F U sf) :
    ((Pairwise.diagram U).op ⋙ F).sections := by
  refine ⟨objPairwiseOfFamily sf, ?_⟩
  let G := (Pairwise.diagram U).op ⋙ F
  rintro (i|⟨i,j⟩) (i'|⟨i',j'⟩) (_|_|_|_)
  · 

Proof state:
case mk.single.mk.single.mk.id_single
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
h : IsCompatible F U sf
G : (CategoryTheory.Pairwise ι)ᵒᵖ ⥤ Type u := (Pairwise.diagram U).op ⋙ F
i : ι
⊢ ((Pairwise.diagram U).op ⋙ F).map { unop := Pairwise.Hom.id_single i }
      (objPairwiseOfFamily sf { unop := Pairwise.single i }) =
    objPairwiseOfFamily sf { unop := Pairwise.single i }

Next tactic:
exact congr_fun (G.map_id <| op <| Pairwise.single i) _
/-- Given a compatible family of sections over open sets, extend it to a
  section of the functor `(Pairwise.diagram U).op ⋙ F`. -/
def IsCompatible.sectionPairwise {sf} (h : IsCompatible F U sf) :
    ((Pairwise.diagram U).op ⋙ F).sections := by
  refine ⟨objPairwiseOfFamily sf, ?_⟩
  let G := (Pairwise.diagram U).op ⋙ F
  rintro (i|⟨i,j⟩) (i'|⟨i',j'⟩) (_|_|_|_)
  · exact congr_fun (G.map_id <| op <| Pairwise.single i) _
  · 

Proof state:
case mk.single.mk.pair.mk.left
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
h : IsCompatible F U sf
G : (CategoryTheory.Pairwise ι)ᵒᵖ ⥤ Type u := (Pairwise.diagram U).op ⋙ F
i j' : ι
⊢ ((Pairwise.diagram U).op ⋙ F).map { unop := Pairwise.Hom.left i j' }
      (objPairwiseOfFamily sf { unop := Pairwise.single i }) =
    objPairwiseOfFamily sf { unop := Pairwise.pair i j' }

Next tactic:
rfl
/-- Given a compatible family of sections over open sets, extend it to a
  section of the functor `(Pairwise.diagram U).op ⋙ F`. -/
def IsCompatible.sectionPairwise {sf} (h : IsCompatible F U sf) :
    ((Pairwise.diagram U).op ⋙ F).sections := by
  refine ⟨objPairwiseOfFamily sf, ?_⟩
  let G := (Pairwise.diagram U).op ⋙ F
  rintro (i|⟨i,j⟩) (i'|⟨i',j'⟩) (_|_|_|_)
  · exact congr_fun (G.map_id <| op <| Pairwise.single i) _
  · rfl
  · 

Proof state:
case mk.single.mk.pair.mk.right
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
h : IsCompatible F U sf
G : (CategoryTheory.Pairwise ι)ᵒᵖ ⥤ Type u := (Pairwise.diagram U).op ⋙ F
i i' : ι
⊢ ((Pairwise.diagram U).op ⋙ F).map { unop := Pairwise.Hom.right i' i }
      (objPairwiseOfFamily sf { unop := Pairwise.single i }) =
    objPairwiseOfFamily sf { unop := Pairwise.pair i' i }

Next tactic:
exact (h i' i).symm
/-- Given a compatible family of sections over open sets, extend it to a
  section of the functor `(Pairwise.diagram U).op ⋙ F`. -/
def IsCompatible.sectionPairwise {sf} (h : IsCompatible F U sf) :
    ((Pairwise.diagram U).op ⋙ F).sections := by
  refine ⟨objPairwiseOfFamily sf, ?_⟩
  let G := (Pairwise.diagram U).op ⋙ F
  rintro (i|⟨i,j⟩) (i'|⟨i',j'⟩) (_|_|_|_)
  · exact congr_fun (G.map_id <| op <| Pairwise.single i) _
  · rfl
  · exact (h i' i).symm
  · 

Proof state:
case mk.pair.mk.pair.mk.id_pair
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
h : IsCompatible F U sf
G : (CategoryTheory.Pairwise ι)ᵒᵖ ⥤ Type u := (Pairwise.diagram U).op ⋙ F
i j : ι
⊢ ((Pairwise.diagram U).op ⋙ F).map { unop := Pairwise.Hom.id_pair i j }
      (objPairwiseOfFamily sf { unop := Pairwise.pair i j }) =
    objPairwiseOfFamily sf { unop := Pairwise.pair i j }

Next tactic:
exact congr_fun (G.map_id <| op <| Pairwise.pair i j) _
theorem isGluing_iff_pairwise {sf s} : IsGluing F U sf s ↔
    ∀ i, (F.mapCone (Pairwise.cocone U).op).π.app i s = objPairwiseOfFamily sf i := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
s : (forget (Type u)).obj (F.obj (op (iSup U)))
⊢ IsGluing F U sf s ↔
    ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
      (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s = objPairwiseOfFamily sf i

Next tactic:
refine ⟨fun h ↦ ?_, fun h i ↦ h (op <| Pairwise.single i)⟩
theorem isGluing_iff_pairwise {sf s} : IsGluing F U sf s ↔
    ∀ i, (F.mapCone (Pairwise.cocone U).op).π.app i s = objPairwiseOfFamily sf i := by
  refine ⟨fun h ↦ ?_, fun h i ↦ h (op <| Pairwise.single i)⟩
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
s : (forget (Type u)).obj (F.obj (op (iSup U)))
h : IsGluing F U sf s
⊢ ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
    (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s = objPairwiseOfFamily sf i

Next tactic:
rintro (i|⟨i,j⟩)
theorem isGluing_iff_pairwise {sf s} : IsGluing F U sf s ↔
    ∀ i, (F.mapCone (Pairwise.cocone U).op).π.app i s = objPairwiseOfFamily sf i := by
  refine ⟨fun h ↦ ?_, fun h i ↦ h (op <| Pairwise.single i)⟩
  rintro (i|⟨i,j⟩)
  · 

Proof state:
case mk.single
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
s : (forget (Type u)).obj (F.obj (op (iSup U)))
h : IsGluing F U sf s
i : ι
⊢ (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app { unop := Pairwise.single i } s =
    objPairwiseOfFamily sf { unop := Pairwise.single i }

Next tactic:
exact h i
theorem isGluing_iff_pairwise {sf s} : IsGluing F U sf s ↔
    ∀ i, (F.mapCone (Pairwise.cocone U).op).π.app i s = objPairwiseOfFamily sf i := by
  refine ⟨fun h ↦ ?_, fun h i ↦ h (op <| Pairwise.single i)⟩
  rintro (i|⟨i,j⟩)
  · exact h i
  · 

Proof state:
case mk.pair
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
s : (forget (Type u)).obj (F.obj (op (iSup U)))
h : IsGluing F U sf s
i j : ι
⊢ (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app { unop := Pairwise.pair i j } s =
    objPairwiseOfFamily sf { unop := Pairwise.pair i j }

Next tactic:
rw [← (F.mapCone (Pairwise.cocone U).op).w (op <| Pairwise.Hom.left i j)]
theorem isGluing_iff_pairwise {sf s} : IsGluing F U sf s ↔
    ∀ i, (F.mapCone (Pairwise.cocone U).op).π.app i s = objPairwiseOfFamily sf i := by
  refine ⟨fun h ↦ ?_, fun h i ↦ h (op <| Pairwise.single i)⟩
  rintro (i|⟨i,j⟩)
  · exact h i
  · rw [← (F.mapCone (Pairwise.cocone U).op).w (op <| Pairwise.Hom.left i j)]
    

Proof state:
case mk.pair
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
s : (forget (Type u)).obj (F.obj (op (iSup U)))
h : IsGluing F U sf s
i j : ι
⊢ ((F.mapCone (Cocone.op (Pairwise.cocone U))).π.app { unop := Pairwise.single i } ≫
        ((Pairwise.diagram U).op ⋙ F).map (op (Pairwise.Hom.left i j)))
      s =
    objPairwiseOfFamily sf { unop := Pairwise.pair i j }

Next tactic:
exact congr_arg _ (h i)
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
⊢ IsSheaf F ↔ IsSheafUniqueGluing F

Next tactic:
simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι : Type x
U : ι → Opens ↑X
⊢ (∀ ⦃ι : Type x⦄ (U : ι → Opens ↑X),
      ∀ s ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F),
        ∃! x, ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ), (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i x = s i) ↔
    ∀ ⦃ι : Type x⦄ (U : ι → Opens ↑X) (sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))),
      IsCompatible F U sf →
        ∃! s,
          ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
            (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s = objPairwiseOfFamily sf i

Next tactic:
refine forall₂_congr fun ι U ↦ ⟨fun h sf cpt ↦ ?_, fun h s hs ↦ ?_⟩
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
  refine forall₂_congr fun ι U ↦ ⟨fun h sf cpt ↦ ?_, fun h s hs ↦ ?_⟩
  · 

Proof state:
case refine_1
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι✝ : Type x
U✝ : ι✝ → Opens ↑X
ι : Type x
U : ι → Opens ↑X
h :
  ∀ s ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F),
    ∃! x, ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ), (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i x = s i
sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))
cpt : IsCompatible F U sf
⊢ ∃! s,
    ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
      (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s = objPairwiseOfFamily sf i

Next tactic:
exact h _ cpt.sectionPairwise.prop
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
  refine forall₂_congr fun ι U ↦ ⟨fun h sf cpt ↦ ?_, fun h s hs ↦ ?_⟩
  · exact h _ cpt.sectionPairwise.prop
  · 

Proof state:
case refine_2
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι✝ : Type x
U✝ : ι✝ → Opens ↑X
ι : Type x
U : ι → Opens ↑X
h :
  ∀ (sf : (i : ι) → (forget (Type u)).obj (F.obj (op (U i)))),
    IsCompatible F U sf →
      ∃! s,
        ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
          (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s = objPairwiseOfFamily sf i
s : (j : (CategoryTheory.Pairwise ι)ᵒᵖ) → ((Pairwise.diagram U).op ⋙ F).obj j
hs : s ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F)
⊢ ∃! x, ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ), (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i x = s i

Next tactic:
specialize h (fun i ↦ s <| op <| Pairwise.single i) fun i j ↦
      (hs <| op <| Pairwise.Hom.left i j).trans (hs <| op <| Pairwise.Hom.right i j).symm
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
  refine forall₂_congr fun ι U ↦ ⟨fun h sf cpt ↦ ?_, fun h s hs ↦ ?_⟩
  · exact h _ cpt.sectionPairwise.prop
  · specialize h (fun i ↦ s <| op <| Pairwise.single i) fun i j ↦
      (hs <| op <| Pairwise.Hom.left i j).trans (hs <| op <| Pairwise.Hom.right i j).symm
    

Proof state:
case refine_2
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι✝ : Type x
U✝ : ι✝ → Opens ↑X
ι : Type x
U : ι → Opens ↑X
s : (j : (CategoryTheory.Pairwise ι)ᵒᵖ) → ((Pairwise.diagram U).op ⋙ F).obj j
hs : s ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F)
h :
  ∃! s_1,
    ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
      (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s_1 =
        objPairwiseOfFamily (fun i => s (op (Pairwise.single i))) i
⊢ ∃! x, ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ), (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i x = s i

Next tactic:
convert h
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
  refine forall₂_congr fun ι U ↦ ⟨fun h sf cpt ↦ ?_, fun h s hs ↦ ?_⟩
  · exact h _ cpt.sectionPairwise.prop
  · specialize h (fun i ↦ s <| op <| Pairwise.single i) fun i j ↦
      (hs <| op <| Pairwise.Hom.left i j).trans (hs <| op <| Pairwise.Hom.right i j).symm
    convert h; 

Proof state:
case h.e'_2.h.h.h.h.e'_3.h.e
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι✝ : Type x
U✝ : ι✝ → Opens ↑X
ι : Type x
U : ι → Opens ↑X
s : (j : (CategoryTheory.Pairwise ι)ᵒᵖ) → ((Pairwise.diagram U).op ⋙ F).obj j
hs : s ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F)
h :
  ∃! s_1,
    ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
      (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s_1 =
        objPairwiseOfFamily (fun i => s (op (Pairwise.single i))) i
e_1✝ : (F.mapCone (Cocone.op (Pairwise.cocone U))).pt = (forget (Type u)).obj (F.obj (op (iSup U)))
x✝ : (F.mapCone (Cocone.op (Pairwise.cocone U))).pt
a✝ : (CategoryTheory.Pairwise ι)ᵒᵖ
⊢ s = objPairwiseOfFamily fun i => s (op (Pairwise.single i))

Next tactic:
ext (i|⟨i,j⟩)
/-- For type-valued presheaves, the sheaf condition in terms of unique gluings is equivalent to the
usual sheaf condition.
-/
theorem isSheaf_iff_isSheafUniqueGluing_types : F.IsSheaf ↔ F.IsSheafUniqueGluing := by
  simp_rw [isSheaf_iff_isSheafPairwiseIntersections, IsSheafPairwiseIntersections,
    Types.isLimit_iff, IsSheafUniqueGluing, isGluing_iff_pairwise]
  refine forall₂_congr fun ι U ↦ ⟨fun h sf cpt ↦ ?_, fun h s hs ↦ ?_⟩
  · exact h _ cpt.sectionPairwise.prop
  · specialize h (fun i ↦ s <| op <| Pairwise.single i) fun i j ↦
      (hs <| op <| Pairwise.Hom.left i j).trans (hs <| op <| Pairwise.Hom.right i j).symm
    convert h; ext (i|⟨i,j⟩)
    · 

Proof state:
case h.e'_2.h.h.h.h.e'_3.h.e.h.mk.single
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : ConcreteCategory C
X : TopCat
F : Presheaf (Type u) X
ι✝ : Type x
U✝ : ι✝ → Opens ↑X
ι : Type x
U : ι → Opens ↑X
s : (j : (CategoryTheory.Pairwise ι)ᵒᵖ) → ((Pairwise.diagram U).op ⋙ F).obj j
hs : s ∈ Functor.sections ((Pairwise.diagram U).op ⋙ F)
h :
  ∃! s_1,
    ∀ (i : (CategoryTheory.Pairwise ι)ᵒᵖ),
      (F.mapCone (Cocone.op (Pairwise.cocone U))).π.app i s_1 =
        objPairwiseOfFamily (fun i => s (op (Pairwise.single i))) i
e_1✝ : (F.mapCone (Cocone.op (Pairwise.cocone U))).pt = (forget (Type u)).obj (F.obj (op (iSup U)))
x✝ : (F.mapCone (Cocone.op (Pairwise.cocone U))).pt
a✝ : (CategoryTheory.Pairwise ι)ᵒᵖ
i : ι
⊢ s { unop := Pairwise.single i } =
    objPairwiseOfFamily (fun i => s (op (Pairwise.single i))) { unop := Pairwise.single i }

Next tactic:
rfl