l3lab/ntp-mathlib huggingface dataset:
/-- A polynomial splits if and only if it has as many roots as its degree. -/
theorem splits_iff_card_roots {p : K[X]} :
    Splits (RingHom.id K) p ↔ Multiset.card p.roots = p.natDegree := by
  constructor
  · intro H
    rw [natDegree_eq_card_roots H, map_id]
  · intro hroots
    rw [splits_iff_exists_multiset (RingHom.id K)]
    use p.roots
    simp only [RingHom.id_apply, map_id]
    

Proof state:
case h
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
p : K[X]
hroots : Multiset.card (roots p) = natDegree p
⊢ p = C (leadingCoeff p) * Multiset.prod (Multiset.map (fun a => X - C a) (roots p))

Next tactic:
exact (C_leadingCoeff_mul_prod_multiset_X_sub_C hroots).symm
theorem aeval_root_derivative_of_splits [Algebra K L] [DecidableEq L] {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (algebraMap K L)) {r : L} (hr : r ∈ P.aroots L) :
    aeval r (Polynomial.derivative P) =
    (((P.aroots L).erase r).map fun a => r - a).prod := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁷ : CommRing R
inst✝⁶ : Field K
inst✝⁵ : Field L
inst✝⁴ : Field F
i : K →+* L
inst✝³ : Algebra R K
inst✝² : Algebra R L
inst✝¹ : Algebra K L
inst✝ : DecidableEq L
P : K[X]
hmo : Monic P
hP : Splits (algebraMap K L) P
r : L
hr : r ∈ aroots P L
⊢ (aeval r) (derivative P) = Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase (aroots P L) r))

Next tactic:
replace hmo := hmo.map (algebraMap K L)
theorem aeval_root_derivative_of_splits [Algebra K L] [DecidableEq L] {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (algebraMap K L)) {r : L} (hr : r ∈ P.aroots L) :
    aeval r (Polynomial.derivative P) =
    (((P.aroots L).erase r).map fun a => r - a).prod := by
  replace hmo := hmo.map (algebraMap K L)
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁷ : CommRing R
inst✝⁶ : Field K
inst✝⁵ : Field L
inst✝⁴ : Field F
i : K →+* L
inst✝³ : Algebra R K
inst✝² : Algebra R L
inst✝¹ : Algebra K L
inst✝ : DecidableEq L
P : K[X]
hP : Splits (algebraMap K L) P
r : L
hr : r ∈ aroots P L
hmo : Monic (map (algebraMap K L) P)
⊢ (aeval r) (derivative P) = Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase (aroots P L) r))

Next tactic:
replace hP := (splits_id_iff_splits (algebraMap K L)).2 hP
theorem aeval_root_derivative_of_splits [Algebra K L] [DecidableEq L] {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (algebraMap K L)) {r : L} (hr : r ∈ P.aroots L) :
    aeval r (Polynomial.derivative P) =
    (((P.aroots L).erase r).map fun a => r - a).prod := by
  replace hmo := hmo.map (algebraMap K L)
  replace hP := (splits_id_iff_splits (algebraMap K L)).2 hP
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁷ : CommRing R
inst✝⁶ : Field K
inst✝⁵ : Field L
inst✝⁴ : Field F
i : K →+* L
inst✝³ : Algebra R K
inst✝² : Algebra R L
inst✝¹ : Algebra K L
inst✝ : DecidableEq L
P : K[X]
r : L
hr : r ∈ aroots P L
hmo : Monic (map (algebraMap K L) P)
hP : Splits (RingHom.id L) (map (algebraMap K L) P)
⊢ (aeval r) (derivative P) = Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase (aroots P L) r))

Next tactic:
rw [aeval_def, ← eval_map, ← derivative_map]
theorem aeval_root_derivative_of_splits [Algebra K L] [DecidableEq L] {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (algebraMap K L)) {r : L} (hr : r ∈ P.aroots L) :
    aeval r (Polynomial.derivative P) =
    (((P.aroots L).erase r).map fun a => r - a).prod := by
  replace hmo := hmo.map (algebraMap K L)
  replace hP := (splits_id_iff_splits (algebraMap K L)).2 hP
  rw [aeval_def, ← eval_map, ← derivative_map]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁷ : CommRing R
inst✝⁶ : Field K
inst✝⁵ : Field L
inst✝⁴ : Field F
i : K →+* L
inst✝³ : Algebra R K
inst✝² : Algebra R L
inst✝¹ : Algebra K L
inst✝ : DecidableEq L
P : K[X]
r : L
hr : r ∈ aroots P L
hmo : Monic (map (algebraMap K L) P)
hP : Splits (RingHom.id L) (map (algebraMap K L) P)
⊢ eval r (derivative (map (algebraMap K L) P)) =
    Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase (aroots P L) r))

Next tactic:
nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
theorem aeval_root_derivative_of_splits [Algebra K L] [DecidableEq L] {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (algebraMap K L)) {r : L} (hr : r ∈ P.aroots L) :
    aeval r (Polynomial.derivative P) =
    (((P.aroots L).erase r).map fun a => r - a).prod := by
  replace hmo := hmo.map (algebraMap K L)
  replace hP := (splits_id_iff_splits (algebraMap K L)).2 hP
  rw [aeval_def, ← eval_map, ← derivative_map]
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁷ : CommRing R
inst✝⁶ : Field K
inst✝⁵ : Field L
inst✝⁴ : Field F
i : K →+* L
inst✝³ : Algebra R K
inst✝² : Algebra R L
inst✝¹ : Algebra K L
inst✝ : DecidableEq L
P : K[X]
r : L
hr : r ∈ aroots P L
hmo : Monic (map (algebraMap K L) P)
hP : Splits (RingHom.id L) (map (algebraMap K L) P)
⊢ eval r (derivative (Multiset.prod (Multiset.map (fun a => X - C a) (roots (map (algebraMap K L) P))))) =
    Multiset.prod (Multiset.map (fun a => r - a) (Multiset.erase (aroots P L) r))

Next tactic:
rw [eval_multiset_prod_X_sub_C_derivative hr]
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ coeff P 0 = (-1) ^ natDegree P * Multiset.prod (roots P)

Next tactic:
nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ coeff (Multiset.prod (Multiset.map (fun a => X - C a) (roots P))) 0 = (-1) ^ natDegree P * Multiset.prod (roots P)

Next tactic:
rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ Multiset.prod (Multiset.map (eval 0 ∘ fun a => X - C a) (roots P)) = (-1) ^ natDegree P * Multiset.prod (roots P)

Next tactic:
simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ Multiset.prod (Multiset.map (fun x => -x) (roots P)) = (-1) ^ natDegree P * Multiset.prod (roots P)

Next tactic:
conv_lhs =>
    congr
    congr
    ext
    rw [neg_eq_neg_one_mul]
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
  conv_lhs =>
    

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
| Multiset.prod (Multiset.map (fun x => -x) (roots P))

Next tactic:
congr
    congr
    ext
    rw [neg_eq_neg_one_mul]
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
  conv_lhs =>
    

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
| Multiset.prod (Multiset.map (fun x => -x) (roots P))

Next tactic:
congr
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
  conv_lhs =>
    congr
    

Proof state:
case a
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
| Multiset.map (fun x => -x) (roots P)

Next tactic:
congr
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
  conv_lhs =>
    congr
    congr
    

Proof state:
case a.f
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
| fun x => -x
case a.s
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
| roots P

Next tactic:
ext
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
  conv_lhs =>
    congr
    congr
    ext
    

Proof state:
case a.f.h
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
x✝ : K
| -x✝
case a.s
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
| roots P

Next tactic:
rw [neg_eq_neg_one_mul]
/-- If `P` is a monic polynomial that splits, then `coeff P 0` equals the product of the roots. -/
theorem prod_roots_eq_coeff_zero_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : coeff P 0 = (-1) ^ P.natDegree * P.roots.prod := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [coeff_zero_eq_eval_zero, eval_multiset_prod, Multiset.map_map]
  simp_rw [Function.comp_apply, eval_sub, eval_X, zero_sub, eval_C]
  conv_lhs =>
    congr
    congr
    ext
    rw [neg_eq_neg_one_mul]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ Multiset.prod (Multiset.map (fun x => -1 * x) (roots P)) = (-1) ^ natDegree P * Multiset.prod (roots P)

Next tactic:
simp only [splits_iff_card_roots.1 hP, neg_mul, one_mul, Multiset.prod_map_neg]
/-- If `P` is a monic polynomial that splits, then `P.nextCoeff` equals the sum of the roots. -/
theorem sum_roots_eq_nextCoeff_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : P.nextCoeff = -P.roots.sum := by
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ nextCoeff P = -Multiset.sum (roots P)

Next tactic:
nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
/-- If `P` is a monic polynomial that splits, then `P.nextCoeff` equals the sum of the roots. -/
theorem sum_roots_eq_nextCoeff_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : P.nextCoeff = -P.roots.sum := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ nextCoeff (Multiset.prod (Multiset.map (fun a => X - C a) (roots P))) = -Multiset.sum (roots P)

Next tactic:
rw [Monic.nextCoeff_multiset_prod _ _ fun a ha => _]
/-- If `P` is a monic polynomial that splits, then `P.nextCoeff` equals the sum of the roots. -/
theorem sum_roots_eq_nextCoeff_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : P.nextCoeff = -P.roots.sum := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [Monic.nextCoeff_multiset_prod _ _ fun a ha => _]
  · 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ Multiset.sum (Multiset.map (fun i => nextCoeff (X - C i)) (roots P)) = -Multiset.sum (roots P)

Next tactic:
simp_rw [nextCoeff_X_sub_C, Multiset.sum_map_neg']
/-- If `P` is a monic polynomial that splits, then `P.nextCoeff` equals the sum of the roots. -/
theorem sum_roots_eq_nextCoeff_of_monic_of_split {P : K[X]} (hmo : P.Monic)
    (hP : P.Splits (RingHom.id K)) : P.nextCoeff = -P.roots.sum := by
  nth_rw 1 [eq_prod_roots_of_monic_of_splits_id hmo hP]
  rw [Monic.nextCoeff_multiset_prod _ _ fun a ha => _]
  · simp_rw [nextCoeff_X_sub_C, Multiset.sum_map_neg']
  · 

Proof state:
R : Type u_1
F : Type u
K : Type v
L : Type w
inst✝⁵ : CommRing R
inst✝⁴ : Field K
inst✝³ : Field L
inst✝² : Field F
i : K →+* L
inst✝¹ : Algebra R K
inst✝ : Algebra R L
P : K[X]
hmo : Monic P
hP : Splits (RingHom.id K) P
⊢ ∀ a ∈ roots P, Monic (X - C a)

Next tactic:
simp only [monic_X_sub_C, implies_true]
@[elementwise, reassoc]
theorem stalkMap_germ {X Y : PresheafedSpace.{_, _, v} C} (α : X ⟶ Y) (U : Opens Y)
    (x : (Opens.map α.base).obj U) :
    Y.presheaf.germ ⟨α.base x.1, x.2⟩ ≫ stalkMap α ↑x = α.c.app (op U) ≫ X.presheaf.germ x := by
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
X Y : PresheafedSpace C
α : X ⟶ Y
U : Opens ↑↑Y
x : ↥((Opens.map α.base).obj U)
⊢ germ Y.presheaf { val := α.base ↑x, property := (_ : ↑x ∈ (Opens.map α.base).obj U) } ≫ stalkMap α ↑x =
    α.c.app (op U) ≫ germ X.presheaf x

Next tactic:
rw [stalkMap, stalkFunctor_map_germ_assoc, stalkPushforward_germ]
@[simp, elementwise, reassoc]
theorem restrictStalkIso_inv_eq_germ {U : TopCat} (X : PresheafedSpace.{_, _, v} C)
    {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (V : Opens U) (x : U) (hx : x ∈ V) :
    X.presheaf.germ ⟨f x, show f x ∈ h.isOpenMap.functor.obj V from ⟨x, hx, rfl⟩⟩ ≫
        (restrictStalkIso X h x).inv =
      (X.restrict h).presheaf.germ ⟨x, hx⟩ :=
  by 

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
U : TopCat
X : PresheafedSpace C
f : U ⟶ ↑X
h : OpenEmbedding ⇑f
V : Opens ↑U
x : ↑U
hx : x ∈ V
⊢ germ X.presheaf { val := f x, property := (_ : f x ∈ (IsOpenMap.functor (_ : IsOpenMap ⇑f)).obj V) } ≫
      (restrictStalkIso X h x).inv =
    germ (restrict X h).presheaf { val := x, property := hx }

Next tactic:
rw [← restrictStalkIso_hom_eq_germ, Category.assoc, Iso.hom_inv_id, Category.comp_id]
theorem restrictStalkIso_inv_eq_ofRestrict {U : TopCat} (X : PresheafedSpace.{_, _, v} C)
    {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (x : U) :
    (X.restrictStalkIso h x).inv = stalkMap (X.ofRestrict h) x := by
  -- We can't use `ext` here due to https://github.com/leanprover/std4/pull/159
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
U : TopCat
X : PresheafedSpace C
f : U ⟶ ↑X
h : OpenEmbedding ⇑f
x : ↑U
⊢ (restrictStalkIso X h x).inv = stalkMap (ofRestrict X h) x

Next tactic:
refine colimit.hom_ext fun V => ?_
theorem restrictStalkIso_inv_eq_ofRestrict {U : TopCat} (X : PresheafedSpace.{_, _, v} C)
    {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (x : U) :
    (X.restrictStalkIso h x).inv = stalkMap (X.ofRestrict h) x := by
  -- We can't use `ext` here due to https://github.com/leanprover/std4/pull/159
  refine colimit.hom_ext fun V => ?_
  

Proof state:
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
U : TopCat
X : PresheafedSpace C
f : U ⟶ ↑X
h : OpenEmbedding ⇑f
x : ↑U
V : (OpenNhds (f x))ᵒᵖ
⊢ colimit.ι (((whiskeringLeft (OpenNhds (f x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj (OpenNhds.inclusion (f x)).op).obj X.presheaf) V ≫
      (restrictStalkIso X h x).inv =
    colimit.ι (((whiskeringLeft (OpenNhds (f x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj (OpenNhds.inclusion (f x)).op).obj X.presheaf)
        V ≫
      stalkMap (ofRestrict X h) x

Next tactic:
induction V with | h V => ?_
theorem restrictStalkIso_inv_eq_ofRestrict {U : TopCat} (X : PresheafedSpace.{_, _, v} C)
    {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (x : U) :
    (X.restrictStalkIso h x).inv = stalkMap (X.ofRestrict h) x := by
  -- We can't use `ext` here due to https://github.com/leanprover/std4/pull/159
  refine colimit.hom_ext fun V => ?_
  induction V with | h V => ?_
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
U : TopCat
X : PresheafedSpace C
f : U ⟶ ↑X
h : OpenEmbedding ⇑f
x : ↑U
V : OpenNhds (f x)
⊢ colimit.ι (((whiskeringLeft (OpenNhds (f x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj (OpenNhds.inclusion (f x)).op).obj X.presheaf)
        (op V) ≫
      (restrictStalkIso X h x).inv =
    colimit.ι (((whiskeringLeft (OpenNhds (f x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj (OpenNhds.inclusion (f x)).op).obj X.presheaf)
        (op V) ≫
      stalkMap (ofRestrict X h) x

Next tactic:
let i : (h.isOpenMap.functorNhds x).obj ((OpenNhds.map f x).obj V) ⟶ V :=
    homOfLE (Set.image_preimage_subset f _)
theorem restrictStalkIso_inv_eq_ofRestrict {U : TopCat} (X : PresheafedSpace.{_, _, v} C)
    {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (x : U) :
    (X.restrictStalkIso h x).inv = stalkMap (X.ofRestrict h) x := by
  -- We can't use `ext` here due to https://github.com/leanprover/std4/pull/159
  refine colimit.hom_ext fun V => ?_
  induction V with | h V => ?_
  let i : (h.isOpenMap.functorNhds x).obj ((OpenNhds.map f x).obj V) ⟶ V :=
    homOfLE (Set.image_preimage_subset f _)
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
U : TopCat
X : PresheafedSpace C
f : U ⟶ ↑X
h : OpenEmbedding ⇑f
x : ↑U
V : OpenNhds (f x)
i : (IsOpenMap.functorNhds (_ : IsOpenMap ⇑f) x).obj ((OpenNhds.map f x).obj V) ⟶ V :=
  homOfLE (_ : ⇑f '' (⇑f ⁻¹' V.obj.1) ⊆ V.obj.1)
⊢ colimit.ι (((whiskeringLeft (OpenNhds (f x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj (OpenNhds.inclusion (f x)).op).obj X.presheaf)
        (op V) ≫
      (restrictStalkIso X h x).inv =
    colimit.ι (((whiskeringLeft (OpenNhds (f x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj (OpenNhds.inclusion (f x)).op).obj X.presheaf)
        (op V) ≫
      stalkMap (ofRestrict X h) x

Next tactic:
erw [Iso.comp_inv_eq, colimit.ι_map_assoc, colimit.ι_map_assoc, colimit.ι_pre]
theorem restrictStalkIso_inv_eq_ofRestrict {U : TopCat} (X : PresheafedSpace.{_, _, v} C)
    {f : U ⟶ (X : TopCat.{v})} (h : OpenEmbedding f) (x : U) :
    (X.restrictStalkIso h x).inv = stalkMap (X.ofRestrict h) x := by
  -- We can't use `ext` here due to https://github.com/leanprover/std4/pull/159
  refine colimit.hom_ext fun V => ?_
  induction V with | h V => ?_
  let i : (h.isOpenMap.functorNhds x).obj ((OpenNhds.map f x).obj V) ⟶ V :=
    homOfLE (Set.image_preimage_subset f _)
  erw [Iso.comp_inv_eq, colimit.ι_map_assoc, colimit.ι_map_assoc, colimit.ι_pre]
  

Proof state:
case h
C : Type u
inst✝¹ : Category.{v, u} C
inst✝ : HasColimits C
U : TopCat
X : PresheafedSpace C
f : U ⟶ ↑X
h : OpenEmbedding ⇑f
x : ↑U
V : OpenNhds (f x)
i : (IsOpenMap.functorNhds (_ : IsOpenMap ⇑f) x).obj ((OpenNhds.map f x).obj V) ⟶ V :=
  homOfLE (_ : ⇑f '' (⇑f ⁻¹' V.obj.1) ⊆ V.obj.1)
⊢ colimit.ι (((whiskeringLeft (OpenNhds (f x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj (OpenNhds.inclusion (f x)).op).obj X.presheaf)
      (op V) =
    ((((whiskeringLeft (OpenNhds ((ofRestrict X h).base x))ᵒᵖ (Opens ↑↑X)ᵒᵖ C).obj
                  (OpenNhds.inclusion ((ofRestrict X h).base x)).op).map
              (ofRestrict X h).c).app
          (op V) ≫
        (whiskerRight (NatTrans.op (OpenNhds.inclusionMapIso (ofRestrict X h).base x).inv) (restrict X h).presheaf).app
            (op V) ≫
          colimit.ι
            (((whiskeringLeft (OpenNhds x)ᵒᵖ (Opens ↑↑(restrict X h))ᵒᵖ C).obj (OpenNhds.inclusion x).op).obj
              (restrict X h).presheaf)
            ((OpenNhds.map (ofRestrict X h).base x).op.obj (op V))) ≫
      (restrictStalkIso X h x).hom

Next tactic:
simp_rw [Category.assoc]