l3lab/ntp-mathlib huggingface dataset:
theorem mulMem' (U : (Opens (ProjectiveSpectrum.top 𝒜))ᵒᵖ) (a b : ∀ x : U.unop, at x.1)
    (ha : (isLocallyFraction 𝒜).pred a) (hb : (isLocallyFraction 𝒜).pred b) :
    (isLocallyFraction 𝒜).pred (a * b) := fun x => by
  rcases ha x with ⟨Va, ma, ia, ja, ⟨ra, ra_mem⟩, ⟨sa, sa_mem⟩, wa⟩
  rcases hb x with ⟨Vb, mb, ib, jb, ⟨rb, rb_mem⟩, ⟨sb, sb_mem⟩, wb⟩
  refine'
    ⟨Va ⊓ Vb, ⟨ma, mb⟩, Opens.infLELeft _ _ ≫ ia, ja + jb,
      ⟨ra * rb, SetLike.mul_mem_graded ra_mem rb_mem⟩,
      ⟨sa * sb, SetLike.mul_mem_graded sa_mem sb_mem⟩, fun y => ⟨fun h => _, _⟩⟩
  · cases' (y : ProjectiveSpectrum.top 𝒜).isPrime.mem_or_mem h with h h
    · choose nin _ using wa ⟨y, (Opens.infLELeft Va Vb y).2⟩; exact nin h
    · choose nin _ using wb ⟨y, (Opens.infLERight Va Vb y).2⟩; exact nin h
  · 

Proof state:
case intro.intro.intro.intro.intro.mk.intro.mk.intro.intro.intro.intro.intro.mk.intro.mk.refine'_2
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
U : (Opens ↑(ProjectiveSpectrum.top 𝒜))ᵒᵖ
a b : (x : ↥U.unop) → at ↑x
ha : PrelocalPredicate.pred (isLocallyFraction 𝒜).toPrelocalPredicate a
hb : PrelocalPredicate.pred (isLocallyFraction 𝒜).toPrelocalPredicate b
x : ↥U.unop
Va : Opens ↑(ProjectiveSpectrum.top 𝒜)
ma : ↑x ∈ Va
ia : Va ⟶ U.unop
ja : ℕ
ra : A
ra_mem : ra ∈ 𝒜 ja
sa : A
sa_mem : sa ∈ 𝒜 ja
wa :
  ∀ (x : ↥Va),
    ∃ (s_nin : ↑{ val := sa, property := sa_mem } ∉ (↑x).asHomogeneousIdeal),
      (fun x => a ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑U.unop) }) x)) x =
        Quotient.mk''
          { deg := ja, num := { val := ra, property := ra_mem }, den := { val := sa, property := sa_mem },
            den_mem := s_nin }
Vb : Opens ↑(ProjectiveSpectrum.top 𝒜)
mb : ↑x ∈ Vb
ib : Vb ⟶ U.unop
jb : ℕ
rb : A
rb_mem : rb ∈ 𝒜 jb
sb : A
sb_mem : sb ∈ 𝒜 jb
wb :
  ∀ (x : ↥Vb),
    ∃ (s_nin : ↑{ val := sb, property := sb_mem } ∉ (↑x).asHomogeneousIdeal),
      (fun x => b ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑U.unop) }) x)) x =
        Quotient.mk''
          { deg := jb, num := { val := rb, property := rb_mem }, den := { val := sb, property := sb_mem },
            den_mem := s_nin }
y : ↥(Va ⊓ Vb)
⊢ (fun x => (a * b) ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑U.unop) }) x)) y =
    Quotient.mk''
      { deg := ja + jb, num := { val := ra * rb, property := (_ : ra * rb ∈ 𝒜 (ja + jb)) },
        den := { val := sa * sb, property := (_ : sa * sb ∈ 𝒜 (ja + jb)) },
        den_mem :=
          (_ : ↑{ val := sa * sb, property := (_ : sa * sb ∈ 𝒜 (ja + jb)) } ∈ (↑y).asHomogeneousIdeal → False) }

Next tactic:
simp only [Pi.mul_apply, RingHom.map_mul]
theorem mulMem' (U : (Opens (ProjectiveSpectrum.top 𝒜))ᵒᵖ) (a b : ∀ x : U.unop, at x.1)
    (ha : (isLocallyFraction 𝒜).pred a) (hb : (isLocallyFraction 𝒜).pred b) :
    (isLocallyFraction 𝒜).pred (a * b) := fun x => by
  rcases ha x with ⟨Va, ma, ia, ja, ⟨ra, ra_mem⟩, ⟨sa, sa_mem⟩, wa⟩
  rcases hb x with ⟨Vb, mb, ib, jb, ⟨rb, rb_mem⟩, ⟨sb, sb_mem⟩, wb⟩
  refine'
    ⟨Va ⊓ Vb, ⟨ma, mb⟩, Opens.infLELeft _ _ ≫ ia, ja + jb,
      ⟨ra * rb, SetLike.mul_mem_graded ra_mem rb_mem⟩,
      ⟨sa * sb, SetLike.mul_mem_graded sa_mem sb_mem⟩, fun y => ⟨fun h => _, _⟩⟩
  · cases' (y : ProjectiveSpectrum.top 𝒜).isPrime.mem_or_mem h with h h
    · choose nin _ using wa ⟨y, (Opens.infLELeft Va Vb y).2⟩; exact nin h
    · choose nin _ using wb ⟨y, (Opens.infLERight Va Vb y).2⟩; exact nin h
  · simp only [Pi.mul_apply, RingHom.map_mul]
    

Proof state:
case intro.intro.intro.intro.intro.mk.intro.mk.intro.intro.intro.intro.intro.mk.intro.mk.refine'_2
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
U : (Opens ↑(ProjectiveSpectrum.top 𝒜))ᵒᵖ
a b : (x : ↥U.unop) → at ↑x
ha : PrelocalPredicate.pred (isLocallyFraction 𝒜).toPrelocalPredicate a
hb : PrelocalPredicate.pred (isLocallyFraction 𝒜).toPrelocalPredicate b
x : ↥U.unop
Va : Opens ↑(ProjectiveSpectrum.top 𝒜)
ma : ↑x ∈ Va
ia : Va ⟶ U.unop
ja : ℕ
ra : A
ra_mem : ra ∈ 𝒜 ja
sa : A
sa_mem : sa ∈ 𝒜 ja
wa :
  ∀ (x : ↥Va),
    ∃ (s_nin : ↑{ val := sa, property := sa_mem } ∉ (↑x).asHomogeneousIdeal),
      (fun x => a ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑U.unop) }) x)) x =
        Quotient.mk''
          { deg := ja, num := { val := ra, property := ra_mem }, den := { val := sa, property := sa_mem },
            den_mem := s_nin }
Vb : Opens ↑(ProjectiveSpectrum.top 𝒜)
mb : ↑x ∈ Vb
ib : Vb ⟶ U.unop
jb : ℕ
rb : A
rb_mem : rb ∈ 𝒜 jb
sb : A
sb_mem : sb ∈ 𝒜 jb
wb :
  ∀ (x : ↥Vb),
    ∃ (s_nin : ↑{ val := sb, property := sb_mem } ∉ (↑x).asHomogeneousIdeal),
      (fun x => b ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑U.unop) }) x)) x =
        Quotient.mk''
          { deg := jb, num := { val := rb, property := rb_mem }, den := { val := sb, property := sb_mem },
            den_mem := s_nin }
y : ↥(Va ⊓ Vb)
⊢ a { val := ↑y, property := (_ : ↑y ∈ ↑U.unop) } * b { val := ↑y, property := (_ : ↑y ∈ ↑U.unop) } =
    Quotient.mk''
      { deg := ja + jb, num := { val := ra * rb, property := (_ : ra * rb ∈ 𝒜 (ja + jb)) },
        den := { val := sa * sb, property := (_ : sa * sb ∈ 𝒜 (ja + jb)) },
        den_mem :=
          (_ : ↑{ val := sa * sb, property := (_ : sa * sb ∈ 𝒜 (ja + jb)) } ∈ (↑y).asHomogeneousIdeal → False) }

Next tactic:
choose nin1 hy1 using wa (Opens.infLELeft Va Vb y)
/-- Some glue, verifying that that structure presheaf valued in `CommRing` agrees with the `Type`
valued structure presheaf.-/
def structurePresheafCompForget :
    structurePresheafInCommRing 𝒜 ⋙ forget CommRingCat ≅ (structureSheafInType 𝒜).1 :=
  NatIso.ofComponents (fun U => Iso.refl _) (by 

Proof state:
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
⊢ ∀ {X Y : (Opens ↑(ProjectiveSpectrum.top 𝒜))ᵒᵖ} (f : X ⟶ Y),
    (structurePresheafInCommRing 𝒜 ⋙ forget CommRingCat).map f ≫
        ((fun U => Iso.refl ((structurePresheafInCommRing 𝒜 ⋙ forget CommRingCat).obj U)) Y).hom =
      ((fun U => Iso.refl ((structurePresheafInCommRing 𝒜 ⋙ forget CommRingCat).obj U)) X).hom ≫
        (structureSheafInType 𝒜).val.map f

Next tactic:
aesop_cat
theorem HomogeneousLocalization.mem_basicOpen (x : ProjectiveSpectrum.top 𝒜) (f : at x) :
    x ∈ ProjectiveSpectrum.basicOpen 𝒜 f.den := by
  

Proof state:
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
x : ↑(ProjectiveSpectrum.top 𝒜)
f : at x
⊢ x ∈ ProjectiveSpectrum.basicOpen 𝒜 (HomogeneousLocalization.den f)

Next tactic:
rw [ProjectiveSpectrum.mem_basicOpen]
theorem HomogeneousLocalization.mem_basicOpen (x : ProjectiveSpectrum.top 𝒜) (f : at x) :
    x ∈ ProjectiveSpectrum.basicOpen 𝒜 f.den := by
  rw [ProjectiveSpectrum.mem_basicOpen]
  

Proof state:
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
x : ↑(ProjectiveSpectrum.top 𝒜)
f : at x
⊢ HomogeneousLocalization.den f ∉ x.asHomogeneousIdeal

Next tactic:
exact f.den_mem
/-- Using `homogeneousLocalizationToStalk`, we construct a ring isomorphism between stalk at `x`
and homogeneous localization at `x` for any point `x` in `Proj`.-/
def Proj.stalkIso' (x : ProjectiveSpectrum.top 𝒜) :
    (Proj.structureSheaf 𝒜).presheaf.stalk x ≃+* CommRingCat.of (at x) :=
  RingEquiv.ofBijective (stalkToFiberRingHom _ x)
    ⟨fun z1 z2 eq1 => by
      

Proof state:
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
x : ↑(ProjectiveSpectrum.top 𝒜)
z1 z2 : ↑(Presheaf.stalk (Sheaf.presheaf (Proj.structureSheaf 𝒜)) x)
eq1 : (stalkToFiberRingHom 𝒜 x) z1 = (stalkToFiberRingHom 𝒜 x) z2
⊢ z1 = z2

Next tactic:
obtain ⟨u1, memu1, s1, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z1
/-- Using `homogeneousLocalizationToStalk`, we construct a ring isomorphism between stalk at `x`
and homogeneous localization at `x` for any point `x` in `Proj`.-/
def Proj.stalkIso' (x : ProjectiveSpectrum.top 𝒜) :
    (Proj.structureSheaf 𝒜).presheaf.stalk x ≃+* CommRingCat.of (at x) :=
  RingEquiv.ofBijective (stalkToFiberRingHom _ x)
    ⟨fun z1 z2 eq1 => by
      obtain ⟨u1, memu1, s1, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z1
      

Proof state:
case intro.intro.intro
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
x : ↑(ProjectiveSpectrum.top 𝒜)
z2 : ↑(Presheaf.stalk (Sheaf.presheaf (Proj.structureSheaf 𝒜)) x)
u1 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memu1 : x ∈ u1
s1 : (forget CommRingCat).obj ((Sheaf.presheaf (Proj.structureSheaf 𝒜)).obj (op u1))
eq1 :
  (stalkToFiberRingHom 𝒜 x)
      ((Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1) =
    (stalkToFiberRingHom 𝒜 x) z2
⊢ (Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1 = z2

Next tactic:
obtain ⟨u2, memu2, s2, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z2
/-- Using `homogeneousLocalizationToStalk`, we construct a ring isomorphism between stalk at `x`
and homogeneous localization at `x` for any point `x` in `Proj`.-/
def Proj.stalkIso' (x : ProjectiveSpectrum.top 𝒜) :
    (Proj.structureSheaf 𝒜).presheaf.stalk x ≃+* CommRingCat.of (at x) :=
  RingEquiv.ofBijective (stalkToFiberRingHom _ x)
    ⟨fun z1 z2 eq1 => by
      obtain ⟨u1, memu1, s1, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z1
      obtain ⟨u2, memu2, s2, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z2
      

Proof state:
case intro.intro.intro.intro.intro.intro
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
x : ↑(ProjectiveSpectrum.top 𝒜)
u1 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memu1 : x ∈ u1
s1 : (forget CommRingCat).obj ((Sheaf.presheaf (Proj.structureSheaf 𝒜)).obj (op u1))
u2 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memu2 : x ∈ u2
s2 : (forget CommRingCat).obj ((Sheaf.presheaf (Proj.structureSheaf 𝒜)).obj (op u2))
eq1 :
  (stalkToFiberRingHom 𝒜 x)
      ((Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1) =
    (stalkToFiberRingHom 𝒜 x)
      ((Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu2 }) s2)
⊢ (Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1 =
    (Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu2 }) s2

Next tactic:
obtain ⟨v1, memv1, i1, ⟨j1, ⟨a1, a1_mem⟩, ⟨b1, b1_mem⟩, hs1⟩⟩ := s1.2 ⟨x, memu1⟩
/-- Using `homogeneousLocalizationToStalk`, we construct a ring isomorphism between stalk at `x`
and homogeneous localization at `x` for any point `x` in `Proj`.-/
def Proj.stalkIso' (x : ProjectiveSpectrum.top 𝒜) :
    (Proj.structureSheaf 𝒜).presheaf.stalk x ≃+* CommRingCat.of (at x) :=
  RingEquiv.ofBijective (stalkToFiberRingHom _ x)
    ⟨fun z1 z2 eq1 => by
      obtain ⟨u1, memu1, s1, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z1
      obtain ⟨u2, memu2, s2, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z2
      obtain ⟨v1, memv1, i1, ⟨j1, ⟨a1, a1_mem⟩, ⟨b1, b1_mem⟩, hs1⟩⟩ := s1.2 ⟨x, memu1⟩
      

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.mk.intro.mk
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
x : ↑(ProjectiveSpectrum.top 𝒜)
u1 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memu1 : x ∈ u1
s1 : (forget CommRingCat).obj ((Sheaf.presheaf (Proj.structureSheaf 𝒜)).obj (op u1))
u2 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memu2 : x ∈ u2
s2 : (forget CommRingCat).obj ((Sheaf.presheaf (Proj.structureSheaf 𝒜)).obj (op u2))
eq1 :
  (stalkToFiberRingHom 𝒜 x)
      ((Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1) =
    (stalkToFiberRingHom 𝒜 x)
      ((Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu2 }) s2)
v1 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memv1 : ↑{ val := x, property := memu1 } ∈ v1
i1 : v1 ⟶ (op u1).unop
j1 : ℕ
a1 : A
a1_mem : a1 ∈ 𝒜 j1
b1 : A
b1_mem : b1 ∈ 𝒜 j1
hs1 :
  ∀ (x : ↥v1),
    ∃ (s_nin : ↑{ val := b1, property := b1_mem } ∉ (↑x).asHomogeneousIdeal),
      (fun x => ↑s1 ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑(op u1).unop) }) x)) x =
        Quotient.mk''
          { deg := j1, num := { val := a1, property := a1_mem }, den := { val := b1, property := b1_mem },
            den_mem := s_nin }
⊢ (Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1 =
    (Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu2 }) s2

Next tactic:
obtain ⟨v2, memv2, i2, ⟨j2, ⟨a2, a2_mem⟩, ⟨b2, b2_mem⟩, hs2⟩⟩ := s2.2 ⟨x, memu2⟩
/-- Using `homogeneousLocalizationToStalk`, we construct a ring isomorphism between stalk at `x`
and homogeneous localization at `x` for any point `x` in `Proj`.-/
def Proj.stalkIso' (x : ProjectiveSpectrum.top 𝒜) :
    (Proj.structureSheaf 𝒜).presheaf.stalk x ≃+* CommRingCat.of (at x) :=
  RingEquiv.ofBijective (stalkToFiberRingHom _ x)
    ⟨fun z1 z2 eq1 => by
      obtain ⟨u1, memu1, s1, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z1
      obtain ⟨u2, memu2, s2, rfl⟩ := (Proj.structureSheaf 𝒜).presheaf.germ_exist x z2
      obtain ⟨v1, memv1, i1, ⟨j1, ⟨a1, a1_mem⟩, ⟨b1, b1_mem⟩, hs1⟩⟩ := s1.2 ⟨x, memu1⟩
      obtain ⟨v2, memv2, i2, ⟨j2, ⟨a2, a2_mem⟩, ⟨b2, b2_mem⟩, hs2⟩⟩ := s2.2 ⟨x, memu2⟩
      

Proof state:
case intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.intro.mk.intro.mk.intro.intro.intro.intro.intro.mk.intro.mk
R : Type u_1
A : Type u_2
inst✝³ : CommRing R
inst✝² : CommRing A
inst✝¹ : Algebra R A
𝒜 : ℕ → Submodule R A
inst✝ : GradedAlgebra 𝒜
x : ↑(ProjectiveSpectrum.top 𝒜)
u1 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memu1 : x ∈ u1
s1 : (forget CommRingCat).obj ((Sheaf.presheaf (Proj.structureSheaf 𝒜)).obj (op u1))
u2 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memu2 : x ∈ u2
s2 : (forget CommRingCat).obj ((Sheaf.presheaf (Proj.structureSheaf 𝒜)).obj (op u2))
eq1 :
  (stalkToFiberRingHom 𝒜 x)
      ((Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1) =
    (stalkToFiberRingHom 𝒜 x)
      ((Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu2 }) s2)
v1 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memv1 : ↑{ val := x, property := memu1 } ∈ v1
i1 : v1 ⟶ (op u1).unop
j1 : ℕ
a1 : A
a1_mem : a1 ∈ 𝒜 j1
b1 : A
b1_mem : b1 ∈ 𝒜 j1
hs1 :
  ∀ (x : ↥v1),
    ∃ (s_nin : ↑{ val := b1, property := b1_mem } ∉ (↑x).asHomogeneousIdeal),
      (fun x => ↑s1 ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑(op u1).unop) }) x)) x =
        Quotient.mk''
          { deg := j1, num := { val := a1, property := a1_mem }, den := { val := b1, property := b1_mem },
            den_mem := s_nin }
v2 : Opens ↑(ProjectiveSpectrum.top 𝒜)
memv2 : ↑{ val := x, property := memu2 } ∈ v2
i2 : v2 ⟶ (op u2).unop
j2 : ℕ
a2 : A
a2_mem : a2 ∈ 𝒜 j2
b2 : A
b2_mem : b2 ∈ 𝒜 j2
hs2 :
  ∀ (x : ↥v2),
    ∃ (s_nin : ↑{ val := b2, property := b2_mem } ∉ (↑x).asHomogeneousIdeal),
      (fun x => ↑s2 ((fun x => { val := ↑x, property := (_ : ↑x ∈ ↑(op u2).unop) }) x)) x =
        Quotient.mk''
          { deg := j2, num := { val := a2, property := a2_mem }, den := { val := b2, property := b2_mem },
            den_mem := s_nin }
⊢ (Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu1 }) s1 =
    (Presheaf.germ (Sheaf.presheaf (Proj.structureSheaf 𝒜)) { val := x, property := memu2 }) s2

Next tactic:
obtain ⟨b1_nin_x, eq2⟩ := hs1 ⟨x, memv1⟩
/-- A finitely presented algebra is of finite type. -/
theorem of_finitePresentation : FinitePresentation R A → FiniteType R A := by
  

Proof state:
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁴ : CommRing R
inst✝³ : CommRing A
inst✝² : Algebra R A
inst✝¹ : CommRing B
inst✝ : Algebra R B
⊢ FinitePresentation R A → FiniteType R A

Next tactic:
rintro ⟨n, f, hf⟩
/-- A finitely presented algebra is of finite type. -/
theorem of_finitePresentation : FinitePresentation R A → FiniteType R A := by
  rintro ⟨n, f, hf⟩
  

Proof state:
case intro.intro
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁴ : CommRing R
inst✝³ : CommRing A
inst✝² : Algebra R A
inst✝¹ : CommRing B
inst✝ : Algebra R B
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f ∧ Ideal.FG (RingHom.ker ↑f)
⊢ FiniteType R A

Next tactic:
apply FiniteType.iff_quotient_mvPolynomial''.2
/-- A finitely presented algebra is of finite type. -/
theorem of_finitePresentation : FinitePresentation R A → FiniteType R A := by
  rintro ⟨n, f, hf⟩
  apply FiniteType.iff_quotient_mvPolynomial''.2
  

Proof state:
case intro.intro
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁴ : CommRing R
inst✝³ : CommRing A
inst✝² : Algebra R A
inst✝¹ : CommRing B
inst✝ : Algebra R B
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f ∧ Ideal.FG (RingHom.ker ↑f)
⊢ ∃ n f, Surjective ⇑f

Next tactic:
exact ⟨n, f, hf.1⟩
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  

Proof state:
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
⊢ FiniteType R A ↔ FinitePresentation R A

Next tactic:
refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
  

Proof state:
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
h : FiniteType R A
⊢ FinitePresentation R A

Next tactic:
obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.1 h
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
  obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.1 h
  

Proof state:
case intro.intro
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
h : FiniteType R A
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f
⊢ FinitePresentation R A

Next tactic:
refine' ⟨n, f, hf, _⟩
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
  obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.1 h
  refine' ⟨n, f, hf, _⟩
  

Proof state:
case intro.intro
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
h : FiniteType R A
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f
⊢ Ideal.FG (RingHom.ker ↑f)

Next tactic:
have hnoet : IsNoetherianRing (MvPolynomial (Fin n) R) := by infer_instance
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
  obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.1 h
  refine' ⟨n, f, hf, _⟩
  have hnoet : IsNoetherianRing (MvPolynomial (Fin n) R) := by 

Proof state:
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
h : FiniteType R A
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f
⊢ IsNoetherianRing (MvPolynomial (Fin n) R)

Next tactic:
infer_instance
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
  obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.1 h
  refine' ⟨n, f, hf, _⟩
  have hnoet : IsNoetherianRing (MvPolynomial (Fin n) R) := by infer_instance
  -- Porting note: rewrote code to help typeclass inference
  

Proof state:
case intro.intro
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
h : FiniteType R A
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f
hnoet : IsNoetherianRing (MvPolynomial (Fin n) R)
⊢ Ideal.FG (RingHom.ker ↑f)

Next tactic:
rw [isNoetherianRing_iff] at hnoet
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
  obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.1 h
  refine' ⟨n, f, hf, _⟩
  have hnoet : IsNoetherianRing (MvPolynomial (Fin n) R) := by infer_instance
  -- Porting note: rewrote code to help typeclass inference
  rw [isNoetherianRing_iff] at hnoet
  

Proof state:
case intro.intro
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
h : FiniteType R A
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f
hnoet : IsNoetherian (MvPolynomial (Fin n) R) (MvPolynomial (Fin n) R)
⊢ Ideal.FG (RingHom.ker ↑f)

Next tactic:
letI : Module (MvPolynomial (Fin n) R) (MvPolynomial (Fin n) R) := Semiring.toModule
/-- An algebra over a Noetherian ring is finitely generated if and only if it is finitely
presented. -/
theorem of_finiteType [IsNoetherianRing R] : FiniteType R A ↔ FinitePresentation R A := by
  refine' ⟨fun h => _, Algebra.FiniteType.of_finitePresentation⟩
  obtain ⟨n, f, hf⟩ := Algebra.FiniteType.iff_quotient_mvPolynomial''.1 h
  refine' ⟨n, f, hf, _⟩
  have hnoet : IsNoetherianRing (MvPolynomial (Fin n) R) := by infer_instance
  -- Porting note: rewrote code to help typeclass inference
  rw [isNoetherianRing_iff] at hnoet
  letI : Module (MvPolynomial (Fin n) R) (MvPolynomial (Fin n) R) := Semiring.toModule
  

Proof state:
case intro.intro
R : Type w₁
A : Type w₂
B : Type w₃
inst✝⁵ : CommRing R
inst✝⁴ : CommRing A
inst✝³ : Algebra R A
inst✝² : CommRing B
inst✝¹ : Algebra R B
inst✝ : IsNoetherianRing R
h : FiniteType R A
n : ℕ
f : MvPolynomial (Fin n) R →ₐ[R] A
hf : Surjective ⇑f
hnoet : IsNoetherian (MvPolynomial (Fin n) R) (MvPolynomial (Fin n) R)
this : Module (MvPolynomial (Fin n) R) (MvPolynomial (Fin n) R) := Semiring.toModule
⊢ Ideal.FG (RingHom.ker ↑f)

Next tactic:
have := hnoet.noetherian (RingHom.ker f.toRingHom)