l3lab/ntp-mathlib huggingface dataset:
theorem IsIntegral.mem_span_pow [Nontrivial R] {x y : S} (hx : IsIntegral R x)
    (hy : ∃ f : R[X], y = aeval x f) :
    y ∈ Submodule.span R (Set.range fun i : Fin (minpoly R x).natDegree => x ^ (i : ℕ)) := by
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : Ring S
inst✝⁶ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁵ : CommRing A
inst✝⁴ : CommRing B
inst✝³ : IsDomain B
inst✝² : Algebra A B
K : Type u_6
inst✝¹ : Field K
inst✝ : Nontrivial R
x y : S
hx : IsIntegral R x
hy : ∃ f, y = (aeval x) f
⊢ y ∈ Submodule.span R (Set.range fun i => x ^ ↑i)

Next tactic:
obtain ⟨f, rfl⟩ := hy
theorem IsIntegral.mem_span_pow [Nontrivial R] {x y : S} (hx : IsIntegral R x)
    (hy : ∃ f : R[X], y = aeval x f) :
    y ∈ Submodule.span R (Set.range fun i : Fin (minpoly R x).natDegree => x ^ (i : ℕ)) := by
  obtain ⟨f, rfl⟩ := hy
  

Proof state:
case intro
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : Ring S
inst✝⁶ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁵ : CommRing A
inst✝⁴ : CommRing B
inst✝³ : IsDomain B
inst✝² : Algebra A B
K : Type u_6
inst✝¹ : Field K
inst✝ : Nontrivial R
x : S
hx : IsIntegral R x
f : R[X]
⊢ (aeval x) f ∈ Submodule.span R (Set.range fun i => x ^ ↑i)

Next tactic:
apply mem_span_pow'.mpr _
theorem IsIntegral.mem_span_pow [Nontrivial R] {x y : S} (hx : IsIntegral R x)
    (hy : ∃ f : R[X], y = aeval x f) :
    y ∈ Submodule.span R (Set.range fun i : Fin (minpoly R x).natDegree => x ^ (i : ℕ)) := by
  obtain ⟨f, rfl⟩ := hy
  apply mem_span_pow'.mpr _
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : Ring S
inst✝⁶ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁵ : CommRing A
inst✝⁴ : CommRing B
inst✝³ : IsDomain B
inst✝² : Algebra A B
K : Type u_6
inst✝¹ : Field K
inst✝ : Nontrivial R
x : S
hx : IsIntegral R x
f : R[X]
⊢ ∃ f_1, degree f_1 < ↑(natDegree (minpoly R x)) ∧ (aeval x) f = (aeval x) f_1

Next tactic:
have := minpoly.monic hx
theorem IsIntegral.mem_span_pow [Nontrivial R] {x y : S} (hx : IsIntegral R x)
    (hy : ∃ f : R[X], y = aeval x f) :
    y ∈ Submodule.span R (Set.range fun i : Fin (minpoly R x).natDegree => x ^ (i : ℕ)) := by
  obtain ⟨f, rfl⟩ := hy
  apply mem_span_pow'.mpr _
  have := minpoly.monic hx
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : Ring S
inst✝⁶ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁵ : CommRing A
inst✝⁴ : CommRing B
inst✝³ : IsDomain B
inst✝² : Algebra A B
K : Type u_6
inst✝¹ : Field K
inst✝ : Nontrivial R
x : S
hx : IsIntegral R x
f : R[X]
this : Monic (minpoly R x)
⊢ ∃ f_1, degree f_1 < ↑(natDegree (minpoly R x)) ∧ (aeval x) f = (aeval x) f_1

Next tactic:
refine' ⟨f %ₘ minpoly R x, (degree_modByMonic_lt _ this).trans_le degree_le_natDegree, _⟩
theorem IsIntegral.mem_span_pow [Nontrivial R] {x y : S} (hx : IsIntegral R x)
    (hy : ∃ f : R[X], y = aeval x f) :
    y ∈ Submodule.span R (Set.range fun i : Fin (minpoly R x).natDegree => x ^ (i : ℕ)) := by
  obtain ⟨f, rfl⟩ := hy
  apply mem_span_pow'.mpr _
  have := minpoly.monic hx
  refine' ⟨f %ₘ minpoly R x, (degree_modByMonic_lt _ this).trans_le degree_le_natDegree, _⟩
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : Ring S
inst✝⁶ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁵ : CommRing A
inst✝⁴ : CommRing B
inst✝³ : IsDomain B
inst✝² : Algebra A B
K : Type u_6
inst✝¹ : Field K
inst✝ : Nontrivial R
x : S
hx : IsIntegral R x
f : R[X]
this : Monic (minpoly R x)
⊢ (aeval x) f = (aeval x) (f %ₘ minpoly R x)

Next tactic:
conv_lhs => rw [← modByMonic_add_div f this]
theorem IsIntegral.mem_span_pow [Nontrivial R] {x y : S} (hx : IsIntegral R x)
    (hy : ∃ f : R[X], y = aeval x f) :
    y ∈ Submodule.span R (Set.range fun i : Fin (minpoly R x).natDegree => x ^ (i : ℕ)) := by
  obtain ⟨f, rfl⟩ := hy
  apply mem_span_pow'.mpr _
  have := minpoly.monic hx
  refine' ⟨f %ₘ minpoly R x, (degree_modByMonic_lt _ this).trans_le degree_le_natDegree, _⟩
  conv_lhs => 

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : Ring S
inst✝⁶ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁵ : CommRing A
inst✝⁴ : CommRing B
inst✝³ : IsDomain B
inst✝² : Algebra A B
K : Type u_6
inst✝¹ : Field K
inst✝ : Nontrivial R
x : S
hx : IsIntegral R x
f : R[X]
this : Monic (minpoly R x)
| (aeval x) f

Next tactic:
rw [← modByMonic_add_div f this]
theorem IsIntegral.mem_span_pow [Nontrivial R] {x y : S} (hx : IsIntegral R x)
    (hy : ∃ f : R[X], y = aeval x f) :
    y ∈ Submodule.span R (Set.range fun i : Fin (minpoly R x).natDegree => x ^ (i : ℕ)) := by
  obtain ⟨f, rfl⟩ := hy
  apply mem_span_pow'.mpr _
  have := minpoly.monic hx
  refine' ⟨f %ₘ minpoly R x, (degree_modByMonic_lt _ this).trans_le degree_le_natDegree, _⟩
  conv_lhs => rw [← modByMonic_add_div f this]
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁸ : CommRing R
inst✝⁷ : Ring S
inst✝⁶ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁵ : CommRing A
inst✝⁴ : CommRing B
inst✝³ : IsDomain B
inst✝² : Algebra A B
K : Type u_6
inst✝¹ : Field K
inst✝ : Nontrivial R
x : S
hx : IsIntegral R x
f : R[X]
this : Monic (minpoly R x)
⊢ (aeval x) (f %ₘ minpoly R x + minpoly R x * (f /ₘ minpoly R x)) = (aeval x) (f %ₘ minpoly R x)

Next tactic:
simp only [add_zero, zero_mul, minpoly.aeval, aeval_add, AlgHom.map_mul]
/-- `PowerBasis.map pb (e : S ≃ₐ[R] S')` is the power basis for `S'` generated by `e pb.gen`. -/
@[simps dim gen basis]
noncomputable def map (pb : PowerBasis R S) (e : S ≃ₐ[R] S') : PowerBasis R S' where
  dim := pb.dim
  basis := pb.basis.map e.toLinearEquiv
  gen := e pb.gen
  basis_eq_pow i := by 

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁹ : CommRing R
inst✝⁸ : Ring S
inst✝⁷ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁶ : CommRing A
inst✝⁵ : CommRing B
inst✝⁴ : IsDomain B
inst✝³ : Algebra A B
K : Type u_6
inst✝² : Field K
S' : Type u_7
inst✝¹ : CommRing S'
inst✝ : Algebra R S'
pb : PowerBasis R S
e : S ≃ₐ[R] S'
i : Fin pb.dim
⊢ (Basis.map pb.basis (AlgEquiv.toLinearEquiv e)) i = e pb.gen ^ ↑i

Next tactic:
rw [Basis.map_apply, pb.basis_eq_pow, e.toLinearEquiv_apply, e.map_pow]
theorem minpolyGen_map (pb : PowerBasis A S) (e : S ≃ₐ[A] S') :
    (pb.map e).minpolyGen = pb.minpolyGen := by
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝¹¹ : CommRing R
inst✝¹⁰ : Ring S
inst✝⁹ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁸ : CommRing A
inst✝⁷ : CommRing B
inst✝⁶ : IsDomain B
inst✝⁵ : Algebra A B
K : Type u_6
inst✝⁴ : Field K
S' : Type u_7
inst✝³ : CommRing S'
inst✝² : Algebra R S'
inst✝¹ : Algebra A S
inst✝ : Algebra A S'
pb : PowerBasis A S
e : S ≃ₐ[A] S'
⊢ minpolyGen (map pb e) = minpolyGen pb

Next tactic:
dsimp only [minpolyGen, map_dim]
theorem minpolyGen_map (pb : PowerBasis A S) (e : S ≃ₐ[A] S') :
    (pb.map e).minpolyGen = pb.minpolyGen := by
  dsimp only [minpolyGen, map_dim]
  -- Turn `Fin (pb.map e).dim` into `Fin pb.dim`
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝¹¹ : CommRing R
inst✝¹⁰ : Ring S
inst✝⁹ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁸ : CommRing A
inst✝⁷ : CommRing B
inst✝⁶ : IsDomain B
inst✝⁵ : Algebra A B
K : Type u_6
inst✝⁴ : Field K
S' : Type u_7
inst✝³ : CommRing S'
inst✝² : Algebra R S'
inst✝¹ : Algebra A S
inst✝ : Algebra A S'
pb : PowerBasis A S
e : S ≃ₐ[A] S'
⊢ (X ^ pb.dim - Finset.sum Finset.univ fun i => C (((map pb e).basis.repr ((map pb e).gen ^ pb.dim)) i) * X ^ ↑i) =
    X ^ pb.dim - Finset.sum Finset.univ fun i => C ((pb.basis.repr (pb.gen ^ pb.dim)) i) * X ^ ↑i

Next tactic:
simp only [LinearEquiv.trans_apply, map_basis, Basis.map_repr, map_gen,
    AlgEquiv.toLinearEquiv_apply, e.toLinearEquiv_symm, AlgEquiv.map_pow,
    AlgEquiv.symm_apply_apply, sub_right_inj]
@[simp]
theorem equivOfRoot_map (pb : PowerBasis A S) (e : S ≃ₐ[A] S') (h₁ h₂) :
    pb.equivOfRoot (pb.map e) h₁ h₂ = e := by
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝¹¹ : CommRing R
inst✝¹⁰ : Ring S
inst✝⁹ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁸ : CommRing A
inst✝⁷ : CommRing B
inst✝⁶ : IsDomain B
inst✝⁵ : Algebra A B
K : Type u_6
inst✝⁴ : Field K
S' : Type u_7
inst✝³ : CommRing S'
inst✝² : Algebra R S'
inst✝¹ : Algebra A S
inst✝ : Algebra A S'
pb : PowerBasis A S
e : S ≃ₐ[A] S'
h₁ : (aeval pb.gen) (minpoly A (map pb e).gen) = 0
h₂ : (aeval (map pb e).gen) (minpoly A pb.gen) = 0
⊢ equivOfRoot pb (map pb e) h₁ h₂ = e

Next tactic:
ext x
@[simp]
theorem equivOfRoot_map (pb : PowerBasis A S) (e : S ≃ₐ[A] S') (h₁ h₂) :
    pb.equivOfRoot (pb.map e) h₁ h₂ = e := by
  ext x
  

Proof state:
case h
R : Type u_1
S : Type u_2
T : Type u_3
inst✝¹¹ : CommRing R
inst✝¹⁰ : Ring S
inst✝⁹ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁸ : CommRing A
inst✝⁷ : CommRing B
inst✝⁶ : IsDomain B
inst✝⁵ : Algebra A B
K : Type u_6
inst✝⁴ : Field K
S' : Type u_7
inst✝³ : CommRing S'
inst✝² : Algebra R S'
inst✝¹ : Algebra A S
inst✝ : Algebra A S'
pb : PowerBasis A S
e : S ≃ₐ[A] S'
h₁ : (aeval pb.gen) (minpoly A (map pb e).gen) = 0
h₂ : (aeval (map pb e).gen) (minpoly A pb.gen) = 0
x : S
⊢ (equivOfRoot pb (map pb e) h₁ h₂) x = e x

Next tactic:
obtain ⟨f, rfl⟩ := pb.exists_eq_aeval' x
@[simp]
theorem equivOfRoot_map (pb : PowerBasis A S) (e : S ≃ₐ[A] S') (h₁ h₂) :
    pb.equivOfRoot (pb.map e) h₁ h₂ = e := by
  ext x
  obtain ⟨f, rfl⟩ := pb.exists_eq_aeval' x
  

Proof state:
case h.intro
R : Type u_1
S : Type u_2
T : Type u_3
inst✝¹¹ : CommRing R
inst✝¹⁰ : Ring S
inst✝⁹ : Algebra R S
A : Type u_4
B : Type u_5
inst✝⁸ : CommRing A
inst✝⁷ : CommRing B
inst✝⁶ : IsDomain B
inst✝⁵ : Algebra A B
K : Type u_6
inst✝⁴ : Field K
S' : Type u_7
inst✝³ : CommRing S'
inst✝² : Algebra R S'
inst✝¹ : Algebra A S
inst✝ : Algebra A S'
pb : PowerBasis A S
e : S ≃ₐ[A] S'
h₁ : (aeval pb.gen) (minpoly A (map pb e).gen) = 0
h₂ : (aeval (map pb e).gen) (minpoly A pb.gen) = 0
f : A[X]
⊢ (equivOfRoot pb (map pb e) h₁ h₂) ((aeval pb.gen) f) = e ((aeval pb.gen) f)

Next tactic:
simp [aeval_algEquiv]
theorem adjoin_gen_eq_top (B : PowerBasis R S) : adjoin R ({B.gen} : Set S) = ⊤ := by
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁷ : CommRing R
inst✝⁶ : Ring S
inst✝⁵ : Algebra R S
A : Type u_4
B✝ : Type u_5
inst✝⁴ : CommRing A
inst✝³ : CommRing B✝
inst✝² : IsDomain B✝
inst✝¹ : Algebra A B✝
K : Type u_6
inst✝ : Field K
B : PowerBasis R S
⊢ adjoin R {B.gen} = ⊤

Next tactic:
rw [← toSubmodule_eq_top, _root_.eq_top_iff, ← B.basis.span_eq, Submodule.span_le]
theorem adjoin_gen_eq_top (B : PowerBasis R S) : adjoin R ({B.gen} : Set S) = ⊤ := by
  rw [← toSubmodule_eq_top, _root_.eq_top_iff, ← B.basis.span_eq, Submodule.span_le]
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁷ : CommRing R
inst✝⁶ : Ring S
inst✝⁵ : Algebra R S
A : Type u_4
B✝ : Type u_5
inst✝⁴ : CommRing A
inst✝³ : CommRing B✝
inst✝² : IsDomain B✝
inst✝¹ : Algebra A B✝
K : Type u_6
inst✝ : Field K
B : PowerBasis R S
⊢ Set.range ⇑B.basis ⊆ ↑(Subalgebra.toSubmodule (adjoin R {B.gen}))

Next tactic:
rintro x ⟨i, rfl⟩
theorem adjoin_gen_eq_top (B : PowerBasis R S) : adjoin R ({B.gen} : Set S) = ⊤ := by
  rw [← toSubmodule_eq_top, _root_.eq_top_iff, ← B.basis.span_eq, Submodule.span_le]
  rintro x ⟨i, rfl⟩
  

Proof state:
case intro
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁷ : CommRing R
inst✝⁶ : Ring S
inst✝⁵ : Algebra R S
A : Type u_4
B✝ : Type u_5
inst✝⁴ : CommRing A
inst✝³ : CommRing B✝
inst✝² : IsDomain B✝
inst✝¹ : Algebra A B✝
K : Type u_6
inst✝ : Field K
B : PowerBasis R S
i : Fin B.dim
⊢ B.basis i ∈ ↑(Subalgebra.toSubmodule (adjoin R {B.gen}))

Next tactic:
rw [B.basis_eq_pow i]
theorem adjoin_gen_eq_top (B : PowerBasis R S) : adjoin R ({B.gen} : Set S) = ⊤ := by
  rw [← toSubmodule_eq_top, _root_.eq_top_iff, ← B.basis.span_eq, Submodule.span_le]
  rintro x ⟨i, rfl⟩
  rw [B.basis_eq_pow i]
  

Proof state:
case intro
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁷ : CommRing R
inst✝⁶ : Ring S
inst✝⁵ : Algebra R S
A : Type u_4
B✝ : Type u_5
inst✝⁴ : CommRing A
inst✝³ : CommRing B✝
inst✝² : IsDomain B✝
inst✝¹ : Algebra A B✝
K : Type u_6
inst✝ : Field K
B : PowerBasis R S
i : Fin B.dim
⊢ B.gen ^ ↑i ∈ ↑(Subalgebra.toSubmodule (adjoin R {B.gen}))

Next tactic:
exact Subalgebra.pow_mem _ (subset_adjoin (Set.mem_singleton _)) _
theorem adjoin_eq_top_of_gen_mem_adjoin {B : PowerBasis R S} {x : S}
    (hx : B.gen ∈ adjoin R ({x} : Set S)) : adjoin R ({x} : Set S) = ⊤ := by
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁷ : CommRing R
inst✝⁶ : Ring S
inst✝⁵ : Algebra R S
A : Type u_4
B✝ : Type u_5
inst✝⁴ : CommRing A
inst✝³ : CommRing B✝
inst✝² : IsDomain B✝
inst✝¹ : Algebra A B✝
K : Type u_6
inst✝ : Field K
B : PowerBasis R S
x : S
hx : B.gen ∈ adjoin R {x}
⊢ adjoin R {x} = ⊤

Next tactic:
rw [_root_.eq_top_iff, ← B.adjoin_gen_eq_top]
theorem adjoin_eq_top_of_gen_mem_adjoin {B : PowerBasis R S} {x : S}
    (hx : B.gen ∈ adjoin R ({x} : Set S)) : adjoin R ({x} : Set S) = ⊤ := by
  rw [_root_.eq_top_iff, ← B.adjoin_gen_eq_top]
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁷ : CommRing R
inst✝⁶ : Ring S
inst✝⁵ : Algebra R S
A : Type u_4
B✝ : Type u_5
inst✝⁴ : CommRing A
inst✝³ : CommRing B✝
inst✝² : IsDomain B✝
inst✝¹ : Algebra A B✝
K : Type u_6
inst✝ : Field K
B : PowerBasis R S
x : S
hx : B.gen ∈ adjoin R {x}
⊢ adjoin R {B.gen} ≤ adjoin R {x}

Next tactic:
refine' adjoin_le _
theorem adjoin_eq_top_of_gen_mem_adjoin {B : PowerBasis R S} {x : S}
    (hx : B.gen ∈ adjoin R ({x} : Set S)) : adjoin R ({x} : Set S) = ⊤ := by
  rw [_root_.eq_top_iff, ← B.adjoin_gen_eq_top]
  refine' adjoin_le _
  

Proof state:
R : Type u_1
S : Type u_2
T : Type u_3
inst✝⁷ : CommRing R
inst✝⁶ : Ring S
inst✝⁵ : Algebra R S
A : Type u_4
B✝ : Type u_5
inst✝⁴ : CommRing A
inst✝³ : CommRing B✝
inst✝² : IsDomain B✝
inst✝¹ : Algebra A B✝
K : Type u_6
inst✝ : Field K
B : PowerBasis R S
x : S
hx : B.gen ∈ adjoin R {x}
⊢ {B.gen} ⊆ ↑(adjoin R {x})

Next tactic:
simp [hx]
/-- The identity functor on a site is cocontinuous. -/
instance isCocontinuous_id : Functor.IsCocontinuous (𝟭 C) J J :=
  ⟨fun h => by 

Proof state:
C : Type u_1
inst✝² : Category.{?u.1875, u_1} C
D : Type u_2
inst✝¹ : Category.{?u.1882, u_2} D
E : Type u_3
inst✝ : Category.{?u.1889, u_3} E
G : C ⥤ D
G' : D ⥤ E
J : GrothendieckTopology C
K : GrothendieckTopology D
L : GrothendieckTopology E
U✝ : C
S✝ : Sieve ((𝟭 C).obj U✝)
h : S✝ ∈ GrothendieckTopology.sieves J ((𝟭 C).obj U✝)
⊢ Sieve.functorPullback (𝟭 C) S✝ ∈ GrothendieckTopology.sieves J U✝

Next tactic:
simpa using h
/-- Given a `G(Y) ⊆ U`, we can find a unique section `X ⟶ ℱ(Y)` that agrees with `x`. -/
def getSection (Y : StructuredArrow (op U) G.op) : X ⟶ ℱ.val.obj Y.right := by
  

Proof state:
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
⊢ X ⟶ ℱ.val.obj Y.right

Next tactic:
letI hom_sh := whiskerRight ((Ran.adjunction A G.op).counit.app ℱ.val) (coyoneda.obj (op X))
/-- Given a `G(Y) ⊆ U`, we can find a unique section `X ⟶ ℱ(Y)` that agrees with `x`. -/
def getSection (Y : StructuredArrow (op U) G.op) : X ⟶ ℱ.val.obj Y.right := by
  letI hom_sh := whiskerRight ((Ran.adjunction A G.op).counit.app ℱ.val) (coyoneda.obj (op X))
  

Proof state:
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
hom_sh : (ran G.op ⋙ (whiskeringLeft Cᵒᵖ Dᵒᵖ A).obj G.op).obj ℱ.val ⋙ coyoneda.obj (op X) ⟶
  (𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X) :=
  whiskerRight ((Ran.adjunction A G.op).counit.app ℱ.val) (coyoneda.obj (op X))
⊢ X ⟶ ℱ.val.obj Y.right

Next tactic:
haveI S' := K.pullback_stable Y.hom.unop hS
/-- Given a `G(Y) ⊆ U`, we can find a unique section `X ⟶ ℱ(Y)` that agrees with `x`. -/
def getSection (Y : StructuredArrow (op U) G.op) : X ⟶ ℱ.val.obj Y.right := by
  letI hom_sh := whiskerRight ((Ran.adjunction A G.op).counit.app ℱ.val) (coyoneda.obj (op X))
  haveI S' := K.pullback_stable Y.hom.unop hS
  

Proof state:
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
hom_sh : (ran G.op ⋙ (whiskeringLeft Cᵒᵖ Dᵒᵖ A).obj G.op).obj ℱ.val ⋙ coyoneda.obj (op X) ⟶
  (𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X) :=
  whiskerRight ((Ran.adjunction A G.op).counit.app ℱ.val) (coyoneda.obj (op X))
S' : Sieve.pullback Y.hom.unop S ∈ GrothendieckTopology.sieves K (G.op.obj Y.right).unop
⊢ X ⟶ ℱ.val.obj Y.right

Next tactic:
haveI hs' := ((hx.pullback Y.3.unop).functorPullback G).compPresheafMap hom_sh
/-- Given a `G(Y) ⊆ U`, we can find a unique section `X ⟶ ℱ(Y)` that agrees with `x`. -/
def getSection (Y : StructuredArrow (op U) G.op) : X ⟶ ℱ.val.obj Y.right := by
  letI hom_sh := whiskerRight ((Ran.adjunction A G.op).counit.app ℱ.val) (coyoneda.obj (op X))
  haveI S' := K.pullback_stable Y.hom.unop hS
  haveI hs' := ((hx.pullback Y.3.unop).functorPullback G).compPresheafMap hom_sh
  

Proof state:
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
hom_sh : (ran G.op ⋙ (whiskeringLeft Cᵒᵖ Dᵒᵖ A).obj G.op).obj ℱ.val ⋙ coyoneda.obj (op X) ⟶
  (𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X) :=
  whiskerRight ((Ran.adjunction A G.op).counit.app ℱ.val) (coyoneda.obj (op X))
S' : Sieve.pullback Y.hom.unop S ∈ GrothendieckTopology.sieves K (G.op.obj Y.right).unop
hs' : Compatible (compPresheafMap hom_sh (FamilyOfElements.functorPullback G (FamilyOfElements.pullback Y.hom.unop x)))
⊢ X ⟶ ℱ.val.obj Y.right

Next tactic:
exact (ℱ.2 X _ (G.cover_lift _ _ S')).amalgamate _ hs'
theorem getSection_is_unique (Y : StructuredArrow (op U) G.op) {y}
    (H : (pulledbackFamily ℱ S x Y).IsAmalgamation y) : y = getSection ℱ hS hx Y := by
  

Proof state:
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
y : ((𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X)).obj (op Y.right.unop)
H : IsAmalgamation (pulledbackFamily ℱ S x Y) y
⊢ y = getSection ℱ hS hx Y

Next tactic:
apply IsSheafFor.isSeparatedFor _ (pulledbackFamily ℱ S x Y)
theorem getSection_is_unique (Y : StructuredArrow (op U) G.op) {y}
    (H : (pulledbackFamily ℱ S x Y).IsAmalgamation y) : y = getSection ℱ hS hx Y := by
  apply IsSheafFor.isSeparatedFor _ (pulledbackFamily ℱ S x Y)
  · 

Proof state:
case a
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
y : ((𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X)).obj (op Y.right.unop)
H : IsAmalgamation (pulledbackFamily ℱ S x Y) y
⊢ IsAmalgamation (pulledbackFamily ℱ S x Y) y

Next tactic:
exact H
theorem getSection_is_unique (Y : StructuredArrow (op U) G.op) {y}
    (H : (pulledbackFamily ℱ S x Y).IsAmalgamation y) : y = getSection ℱ hS hx Y := by
  apply IsSheafFor.isSeparatedFor _ (pulledbackFamily ℱ S x Y)
  · exact H
  · 

Proof state:
case a
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
y : ((𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X)).obj (op Y.right.unop)
H : IsAmalgamation (pulledbackFamily ℱ S x Y) y
⊢ IsAmalgamation (pulledbackFamily ℱ S x Y) (getSection ℱ hS hx Y)

Next tactic:
apply getSection_isAmalgamation
theorem getSection_is_unique (Y : StructuredArrow (op U) G.op) {y}
    (H : (pulledbackFamily ℱ S x Y).IsAmalgamation y) : y = getSection ℱ hS hx Y := by
  apply IsSheafFor.isSeparatedFor _ (pulledbackFamily ℱ S x Y)
  · exact H
  · apply getSection_isAmalgamation
  · 

Proof state:
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y : StructuredArrow (op U) G.op
y : ((𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X)).obj (op Y.right.unop)
H : IsAmalgamation (pulledbackFamily ℱ S x Y) y
⊢ IsSheafFor ((𝟭 (Cᵒᵖ ⥤ A)).obj ℱ.val ⋙ coyoneda.obj (op X))
    (Presieve.functorPullback G (Sieve.pullback Y.hom.unop S).arrows)

Next tactic:
exact ℱ.2 X _ (G.cover_lift _ _ (K.pullback_stable Y.hom.unop hS))
@[simp]
theorem getSection_commute {Y Z : StructuredArrow (op U) G.op} (f : Y ⟶ Z) :
    getSection ℱ hS hx Y ≫ ℱ.val.map f.right = getSection ℱ hS hx Z := by
  

Proof state:
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y Z : StructuredArrow (op U) G.op
f : Y ⟶ Z
⊢ getSection ℱ hS hx Y ≫ ℱ.val.map f.right = getSection ℱ hS hx Z

Next tactic:
apply getSection_is_unique
@[simp]
theorem getSection_commute {Y Z : StructuredArrow (op U) G.op} (f : Y ⟶ Z) :
    getSection ℱ hS hx Y ≫ ℱ.val.map f.right = getSection ℱ hS hx Z := by
  apply getSection_is_unique
  

Proof state:
case H
C D : Type u
inst✝⁴ : Category.{v, u} C
inst✝³ : Category.{v, u} D
G : C ⥤ D
A : Type w
inst✝² : Category.{max u v, w} A
inst✝¹ : HasLimits A
J : GrothendieckTopology C
K : GrothendieckTopology D
inst✝ : Functor.IsCocontinuous G J K
ℱ : Sheaf J A
X : A
U : D
S : Sieve U
hS : S ∈ GrothendieckTopology.sieves K U
x : FamilyOfElements ((ran G.op).obj ℱ.val ⋙ coyoneda.obj (op X)) S.arrows
hx : Compatible x
Y Z : StructuredArrow (op U) G.op
f : Y ⟶ Z
⊢ IsAmalgamation (pulledbackFamily ℱ S x Z) (getSection ℱ hS hx Y ≫ ℱ.val.map f.right)

Next tactic:
intro V' fV' hV'