l3lab/ntp-mathlib huggingface dataset:
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  

Proof state:
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
⊢ FG ↑I

Next tactic:
have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    

Proof state:
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
⊢ 1 ∈ ↑I * ↑I⁻¹

Next tactic:
rw [I.mul_inv]
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    

Proof state:
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
⊢ 1 ∈ 1

Next tactic:
exact one_le.mp le_rfl
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  

Proof state:
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
⊢ FG ↑I

Next tactic:
obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
  

Proof state:
case intro.intro.intro.intro
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
T T' : Finset A
hT : ↑T ⊆ ↑↑I
hT' : ↑T' ⊆ ↑↑I⁻¹
one_mem : 1 ∈ span R (↑T * ↑T')
⊢ FG ↑I

Next tactic:
refine' ⟨T, span_eq_of_le _ hT _⟩
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
  refine' ⟨T, span_eq_of_le _ hT _⟩
  

Proof state:
case intro.intro.intro.intro
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
T T' : Finset A
hT : ↑T ⊆ ↑↑I
hT' : ↑T' ⊆ ↑↑I⁻¹
one_mem : 1 ∈ span R (↑T * ↑T')
⊢ ↑I ≤ span R ↑T

Next tactic:
rw [← one_mul I, ← mul_one (span R (T : Set A))]
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
  refine' ⟨T, span_eq_of_le _ hT _⟩
  rw [← one_mul I, ← mul_one (span R (T : Set A))]
  

Proof state:
case intro.intro.intro.intro
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
T T' : Finset A
hT : ↑T ⊆ ↑↑I
hT' : ↑T' ⊆ ↑↑I⁻¹
one_mem : 1 ∈ span R (↑T * ↑T')
⊢ ↑(1 * I) ≤ span R ↑T * 1

Next tactic:
conv_rhs => rw [← I.inv_mul, ← mul_assoc]
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
  refine' ⟨T, span_eq_of_le _ hT _⟩
  rw [← one_mul I, ← mul_one (span R (T : Set A))]
  conv_rhs => 

Proof state:
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
T T' : Finset A
hT : ↑T ⊆ ↑↑I
hT' : ↑T' ⊆ ↑↑I⁻¹
one_mem : 1 ∈ span R (↑T * ↑T')
| span R ↑T * 1

Next tactic:
rw [← I.inv_mul, ← mul_assoc]
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
  refine' ⟨T, span_eq_of_le _ hT _⟩
  rw [← one_mul I, ← mul_one (span R (T : Set A))]
  conv_rhs => rw [← I.inv_mul, ← mul_assoc]
  

Proof state:
case intro.intro.intro.intro
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
T T' : Finset A
hT : ↑T ⊆ ↑↑I
hT' : ↑T' ⊆ ↑↑I⁻¹
one_mem : 1 ∈ span R (↑T * ↑T')
⊢ ↑(1 * I) ≤ span R ↑T * ↑I⁻¹ * ↑I

Next tactic:
refine' mul_le_mul_left (le_trans _ <| mul_le_mul_right <| span_le.mpr hT')
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
  refine' ⟨T, span_eq_of_le _ hT _⟩
  rw [← one_mul I, ← mul_one (span R (T : Set A))]
  conv_rhs => rw [← I.inv_mul, ← mul_assoc]
  refine' mul_le_mul_left (le_trans _ <| mul_le_mul_right <| span_le.mpr hT')
  

Proof state:
case intro.intro.intro.intro
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
T T' : Finset A
hT : ↑T ⊆ ↑↑I
hT' : ↑T' ⊆ ↑↑I⁻¹
one_mem : 1 ∈ span R (↑T * ↑T')
⊢ ↑1 ≤ span R ↑T * span R ↑T'

Next tactic:
simp only [Units.val_one, span_mul_span]
theorem fg_unit {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (I : (Submodule R A)ˣ) :
    (I : Submodule R A).FG := by
  have : (1 : A) ∈ (I * ↑I⁻¹ : Submodule R A) := by
    rw [I.mul_inv]
    exact one_le.mp le_rfl
  obtain ⟨T, T', hT, hT', one_mem⟩ := mem_span_mul_finite_of_mem_mul this
  refine' ⟨T, span_eq_of_le _ hT _⟩
  rw [← one_mul I, ← mul_one (span R (T : Set A))]
  conv_rhs => rw [← I.inv_mul, ← mul_assoc]
  refine' mul_le_mul_left (le_trans _ <| mul_le_mul_right <| span_le.mpr hT')
  simp only [Units.val_one, span_mul_span]
  

Proof state:
case intro.intro.intro.intro
R✝ : Type u_1
M : Type u_2
inst✝⁵ : Semiring R✝
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R✝ M
R : Type u_3
A : Type u_4
inst✝² : CommSemiring R
inst✝¹ : Semiring A
inst✝ : Algebra R A
I : (Submodule R A)ˣ
this : 1 ∈ ↑I * ↑I⁻¹
T T' : Finset A
hT : ↑T ⊆ ↑↑I
hT' : ↑T' ⊆ ↑↑I⁻¹
one_mem : 1 ∈ span R (↑T * ↑T')
⊢ 1 ≤ span R (↑T * ↑T')

Next tactic:
rwa [one_le]
theorem fg_span {s : Set M} (hs : s.Finite) : FG (span R s) :=
  ⟨hs.toFinset, by 

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
s : Set M
hs : Set.Finite s
⊢ span R ↑(Finite.toFinset hs) = span R s

Next tactic:
rw [hs.coe_toFinset]
theorem FG.sup {N₁ N₂ : Submodule R M} (hN₁ : N₁.FG) (hN₂ : N₂.FG) : (N₁ ⊔ N₂).FG :=
  let ⟨t₁, ht₁⟩ := fg_def.1 hN₁
  let ⟨t₂, ht₂⟩ := fg_def.1 hN₂
  fg_def.2 ⟨t₁ ∪ t₂, ht₁.1.union ht₂.1, by 

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
N₁ N₂ : Submodule R M
hN₁ : FG N₁
hN₂ : FG N₂
t₁ : Set M
ht₁ : Set.Finite t₁ ∧ span R t₁ = N₁
t₂ : Set M
ht₂ : Set.Finite t₂ ∧ span R t₂ = N₂
⊢ span R (t₁ ∪ t₂) = N₁ ⊔ N₂

Next tactic:
rw [span_union, ht₁.2, ht₂.2]
theorem fg_biSup {ι : Type*} (s : Finset ι) (N : ι → Submodule R M) (h : ∀ i ∈ s, (N i).FG) :
    (⨆ i ∈ s, N i).FG := by 

Proof state:
R : Type u_1
M : Type u_2
inst✝² : Semiring R
inst✝¹ : AddCommMonoid M
inst✝ : Module R M
ι : Type u_3
s : Finset ι
N : ι → Submodule R M
h : ∀ i ∈ s, FG (N i)
⊢ FG (⨆ i ∈ s, N i)

Next tactic:
simpa only [Finset.sup_eq_iSup] using fg_finset_sup s N h
theorem fg_iSup {ι : Type*} [Finite ι] (N : ι → Submodule R M) (h : ∀ i, (N i).FG) :
    (iSup N).FG := by
  

Proof state:
R : Type u_1
M : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
ι : Type u_3
inst✝ : Finite ι
N : ι → Submodule R M
h : ∀ (i : ι), FG (N i)
⊢ FG (iSup N)

Next tactic:
cases nonempty_fintype ι
theorem fg_iSup {ι : Type*} [Finite ι] (N : ι → Submodule R M) (h : ∀ i, (N i).FG) :
    (iSup N).FG := by
  cases nonempty_fintype ι
  

Proof state:
case intro
R : Type u_1
M : Type u_2
inst✝³ : Semiring R
inst✝² : AddCommMonoid M
inst✝¹ : Module R M
ι : Type u_3
inst✝ : Finite ι
N : ι → Submodule R M
h : ∀ (i : ι), FG (N i)
val✝ : Fintype ι
⊢ FG (iSup N)

Next tactic:
simpa using fg_biSup Finset.univ N fun i _ => h i
theorem FG.map {N : Submodule R M} (hs : N.FG) : (N.map f).FG :=
  let ⟨t, ht⟩ := fg_def.1 hs
  fg_def.2 ⟨f '' t, ht.1.image _, by 

Proof state:
R : Type u_1
M : Type u_2
inst✝⁴ : Semiring R
inst✝³ : AddCommMonoid M
inst✝² : Module R M
P : Type u_3
inst✝¹ : AddCommMonoid P
inst✝ : Module R P
f : M →ₗ[R] P
N : Submodule R M
hs : FG N
t : Set M
ht : Set.Finite t ∧ span R t = N
⊢ span R (⇑f '' t) = Submodule.map f N

Next tactic:
rw [span_image, ht.2]
theorem fg_of_fg_map_injective (f : M →ₗ[R] P) (hf : Function.Injective f) {N : Submodule R M}
    (hfn : (N.map f).FG) : N.FG :=
  let ⟨t, ht⟩ := hfn
  ⟨t.preimage f fun x _ y _ h => hf h,
    Submodule.map_injective_of_injective hf <| by
      

Proof state:
R : Type u_1
M : Type u_2
inst✝⁴ : Semiring R
inst✝³ : AddCommMonoid M
inst✝² : Module R M
P : Type u_3
inst✝¹ : AddCommMonoid P
inst✝ : Module R P
f✝ f : M →ₗ[R] P
hf : Function.Injective ⇑f
N : Submodule R M
hfn : FG (map f N)
t : Finset P
ht : span R ↑t = map f N
⊢ map f (span R ↑(Finset.preimage t ⇑f (_ : ∀ x ∈ ⇑f ⁻¹' ↑t, ∀ y ∈ ⇑f ⁻¹' ↑t, f x = f y → x = y))) = map f N

Next tactic:
rw [map_span, Finset.coe_preimage, Set.image_preimage_eq_inter_range,
        Set.inter_eq_self_of_subset_left, ht]
theorem fg_of_fg_map_injective (f : M →ₗ[R] P) (hf : Function.Injective f) {N : Submodule R M}
    (hfn : (N.map f).FG) : N.FG :=
  let ⟨t, ht⟩ := hfn
  ⟨t.preimage f fun x _ y _ h => hf h,
    Submodule.map_injective_of_injective hf <| by
      rw [map_span, Finset.coe_preimage, Set.image_preimage_eq_inter_range,
        Set.inter_eq_self_of_subset_left, ht]
      

Proof state:
R : Type u_1
M : Type u_2
inst✝⁴ : Semiring R
inst✝³ : AddCommMonoid M
inst✝² : Module R M
P : Type u_3
inst✝¹ : AddCommMonoid P
inst✝ : Module R P
f✝ f : M →ₗ[R] P
hf : Function.Injective ⇑f
N : Submodule R M
hfn : FG (map f N)
t : Finset P
ht : span R ↑t = map f N
⊢ ↑t ⊆ range ⇑f

Next tactic:
rw [← LinearMap.range_coe, ← span_le, ht, ← map_top]
theorem fg_of_fg_map_injective (f : M →ₗ[R] P) (hf : Function.Injective f) {N : Submodule R M}
    (hfn : (N.map f).FG) : N.FG :=
  let ⟨t, ht⟩ := hfn
  ⟨t.preimage f fun x _ y _ h => hf h,
    Submodule.map_injective_of_injective hf <| by
      rw [map_span, Finset.coe_preimage, Set.image_preimage_eq_inter_range,
        Set.inter_eq_self_of_subset_left, ht]
      rw [← LinearMap.range_coe, ← span_le, ht, ← map_top]
      

Proof state:
R : Type u_1
M : Type u_2
inst✝⁴ : Semiring R
inst✝³ : AddCommMonoid M
inst✝² : Module R M
P : Type u_3
inst✝¹ : AddCommMonoid P
inst✝ : Module R P
f✝ f : M →ₗ[R] P
hf : Function.Injective ⇑f
N : Submodule R M
hfn : FG (map f N)
t : Finset P
ht : span R ↑t = map f N
⊢ map f N ≤ map f ⊤

Next tactic:
exact map_mono le_top
theorem fg_top (N : Submodule R M) : (⊤ : Submodule R N).FG ↔ N.FG :=
  ⟨fun h => N.range_subtype ▸ map_top N.subtype ▸ h.map _, fun h =>
    fg_of_fg_map_injective N.subtype Subtype.val_injective <| by 

Proof state:
R : Type u_1
M : Type u_2
inst✝⁴ : Semiring R
inst✝³ : AddCommMonoid M
inst✝² : Module R M
P : Type u_3
inst✝¹ : AddCommMonoid P
inst✝ : Module R P
f : M →ₗ[R] P
N : Submodule R M
h : FG N
⊢ FG (map (Submodule.subtype N) ⊤)

Next tactic:
rwa [map_top, range_subtype]
theorem FG.prod {sb : Submodule R M} {sc : Submodule R P} (hsb : sb.FG) (hsc : sc.FG) :
    (sb.prod sc).FG :=
  let ⟨tb, htb⟩ := fg_def.1 hsb
  let ⟨tc, htc⟩ := fg_def.1 hsc
  fg_def.2
    ⟨LinearMap.inl R M P '' tb ∪ LinearMap.inr R M P '' tc, (htb.1.image _).union (htc.1.image _),
      by 

Proof state:
R : Type u_1
M : Type u_2
inst✝⁴ : Semiring R
inst✝³ : AddCommMonoid M
inst✝² : Module R M
P : Type u_3
inst✝¹ : AddCommMonoid P
inst✝ : Module R P
f : M →ₗ[R] P
sb : Submodule R M
sc : Submodule R P
hsb : FG sb
hsc : FG sc
tb : Set M
htb : Set.Finite tb ∧ span R tb = sb
tc : Set P
htc : Set.Finite tc ∧ span R tc = sc
⊢ span R (⇑(LinearMap.inl R M P) '' tb ∪ ⇑(LinearMap.inr R M P) '' tc) = Submodule.prod sb sc

Next tactic:
rw [LinearMap.span_inl_union_inr, htb.2, htc.2]
theorem fg_pi {ι : Type*} {M : ι → Type*} [Finite ι] [∀ i, AddCommMonoid (M i)]
    [∀ i, Module R (M i)] {p : ∀ i, Submodule R (M i)} (hsb : ∀ i, (p i).FG) :
    (Submodule.pi Set.univ p).FG := by
  

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝⁷ : Semiring R
inst✝⁶ : AddCommMonoid M✝
inst✝⁵ : Module R M✝
P : Type u_3
inst✝⁴ : AddCommMonoid P
inst✝³ : Module R P
f : M✝ →ₗ[R] P
ι : Type u_4
M : ι → Type u_5
inst✝² : Finite ι
inst✝¹ : (i : ι) → AddCommMonoid (M i)
inst✝ : (i : ι) → Module R (M i)
p : (i : ι) → Submodule R (M i)
hsb : ∀ (i : ι), FG (p i)
⊢ FG (pi univ p)

Next tactic:
classical
    simp_rw [fg_def] at hsb ⊢
    choose t htf hts using hsb
    -- Porting note: `refine'` doesn't work here
    refine
      ⟨⋃ i, (LinearMap.single i : _ →ₗ[R] _) '' t i, Set.finite_iUnion fun i => (htf i).image _, ?_⟩
    simp_rw [span_iUnion, span_image, hts, Submodule.iSup_map_single]
theorem fg_pi {ι : Type*} {M : ι → Type*} [Finite ι] [∀ i, AddCommMonoid (M i)]
    [∀ i, Module R (M i)] {p : ∀ i, Submodule R (M i)} (hsb : ∀ i, (p i).FG) :
    (Submodule.pi Set.univ p).FG := by
  classical
    

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝⁷ : Semiring R
inst✝⁶ : AddCommMonoid M✝
inst✝⁵ : Module R M✝
P : Type u_3
inst✝⁴ : AddCommMonoid P
inst✝³ : Module R P
f : M✝ →ₗ[R] P
ι : Type u_4
M : ι → Type u_5
inst✝² : Finite ι
inst✝¹ : (i : ι) → AddCommMonoid (M i)
inst✝ : (i : ι) → Module R (M i)
p : (i : ι) → Submodule R (M i)
hsb : ∀ (i : ι), FG (p i)
⊢ FG (pi univ p)

Next tactic:
simp_rw [fg_def] at hsb ⊢
theorem fg_pi {ι : Type*} {M : ι → Type*} [Finite ι] [∀ i, AddCommMonoid (M i)]
    [∀ i, Module R (M i)] {p : ∀ i, Submodule R (M i)} (hsb : ∀ i, (p i).FG) :
    (Submodule.pi Set.univ p).FG := by
  classical
    simp_rw [fg_def] at hsb ⊢
    

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝⁷ : Semiring R
inst✝⁶ : AddCommMonoid M✝
inst✝⁵ : Module R M✝
P : Type u_3
inst✝⁴ : AddCommMonoid P
inst✝³ : Module R P
f : M✝ →ₗ[R] P
ι : Type u_4
M : ι → Type u_5
inst✝² : Finite ι
inst✝¹ : (i : ι) → AddCommMonoid (M i)
inst✝ : (i : ι) → Module R (M i)
p : (i : ι) → Submodule R (M i)
hsb : ∀ (i : ι), ∃ S, Set.Finite S ∧ span R S = p i
⊢ ∃ S, Set.Finite S ∧ span R S = pi univ p

Next tactic:
choose t htf hts using hsb
theorem fg_pi {ι : Type*} {M : ι → Type*} [Finite ι] [∀ i, AddCommMonoid (M i)]
    [∀ i, Module R (M i)] {p : ∀ i, Submodule R (M i)} (hsb : ∀ i, (p i).FG) :
    (Submodule.pi Set.univ p).FG := by
  classical
    simp_rw [fg_def] at hsb ⊢
    choose t htf hts using hsb
    -- Porting note: `refine'` doesn't work here
    

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝⁷ : Semiring R
inst✝⁶ : AddCommMonoid M✝
inst✝⁵ : Module R M✝
P : Type u_3
inst✝⁴ : AddCommMonoid P
inst✝³ : Module R P
f : M✝ →ₗ[R] P
ι : Type u_4
M : ι → Type u_5
inst✝² : Finite ι
inst✝¹ : (i : ι) → AddCommMonoid (M i)
inst✝ : (i : ι) → Module R (M i)
p : (i : ι) → Submodule R (M i)
t : (i : ι) → Set (M i)
htf : ∀ (i : ι), Set.Finite (t i)
hts : ∀ (i : ι), span R (t i) = p i
⊢ ∃ S, Set.Finite S ∧ span R S = pi univ p

Next tactic:
refine
      ⟨⋃ i, (LinearMap.single i : _ →ₗ[R] _) '' t i, Set.finite_iUnion fun i => (htf i).image _, ?_⟩
theorem fg_pi {ι : Type*} {M : ι → Type*} [Finite ι] [∀ i, AddCommMonoid (M i)]
    [∀ i, Module R (M i)] {p : ∀ i, Submodule R (M i)} (hsb : ∀ i, (p i).FG) :
    (Submodule.pi Set.univ p).FG := by
  classical
    simp_rw [fg_def] at hsb ⊢
    choose t htf hts using hsb
    -- Porting note: `refine'` doesn't work here
    refine
      ⟨⋃ i, (LinearMap.single i : _ →ₗ[R] _) '' t i, Set.finite_iUnion fun i => (htf i).image _, ?_⟩
    

Proof state:
R : Type u_1
M✝ : Type u_2
inst✝⁷ : Semiring R
inst✝⁶ : AddCommMonoid M✝
inst✝⁵ : Module R M✝
P : Type u_3
inst✝⁴ : AddCommMonoid P
inst✝³ : Module R P
f : M✝ →ₗ[R] P
ι : Type u_4
M : ι → Type u_5
inst✝² : Finite ι
inst✝¹ : (i : ι) → AddCommMonoid (M i)
inst✝ : (i : ι) → Module R (M i)
p : (i : ι) → Submodule R (M i)
t : (i : ι) → Set (M i)
htf : ∀ (i : ι), Set.Finite (t i)
hts : ∀ (i : ι), span R (t i) = p i
⊢ span R (⋃ i, ⇑(LinearMap.single i) '' t i) = pi univ p

Next tactic:
simp_rw [span_iUnion, span_image, hts, Submodule.iSup_map_single]
/-- If 0 → M' → M → M'' → 0 is exact and M' and M'' are
finitely generated then so is M. -/
theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Module R M]
    [AddCommGroup P] [Module R P] (f : M →ₗ[R] P) {s : Submodule R M}
    (hs1 : (s.map f).FG)
    (hs2 : (s ⊓ LinearMap.ker f).FG) : s.FG := by
  

Proof state:
R✝ : Type u_1
M✝ : Type u_2
inst✝⁹ : Semiring R✝
inst✝⁸ : AddCommMonoid M✝
inst✝⁷ : Module R✝ M✝
P✝ : Type u_3
inst✝⁶ : AddCommMonoid P✝
inst✝⁵ : Module R✝ P✝
f✝ : M✝ →ₗ[R✝] P✝
R : Type u_4
M : Type u_5
P : Type u_6
inst✝⁴ : Ring R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup P
inst✝ : Module R P
f : M →ₗ[R] P
s : Submodule R M
hs1 : FG (map f s)
hs2 : FG (s ⊓ LinearMap.ker f)
⊢ FG s

Next tactic:
haveI := Classical.decEq R
/-- If 0 → M' → M → M'' → 0 is exact and M' and M'' are
finitely generated then so is M. -/
theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Module R M]
    [AddCommGroup P] [Module R P] (f : M →ₗ[R] P) {s : Submodule R M}
    (hs1 : (s.map f).FG)
    (hs2 : (s ⊓ LinearMap.ker f).FG) : s.FG := by
  haveI := Classical.decEq R
  

Proof state:
R✝ : Type u_1
M✝ : Type u_2
inst✝⁹ : Semiring R✝
inst✝⁸ : AddCommMonoid M✝
inst✝⁷ : Module R✝ M✝
P✝ : Type u_3
inst✝⁶ : AddCommMonoid P✝
inst✝⁵ : Module R✝ P✝
f✝ : M✝ →ₗ[R✝] P✝
R : Type u_4
M : Type u_5
P : Type u_6
inst✝⁴ : Ring R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup P
inst✝ : Module R P
f : M →ₗ[R] P
s : Submodule R M
hs1 : FG (map f s)
hs2 : FG (s ⊓ LinearMap.ker f)
this : DecidableEq R
⊢ FG s

Next tactic:
haveI := Classical.decEq M
/-- If 0 → M' → M → M'' → 0 is exact and M' and M'' are
finitely generated then so is M. -/
theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Module R M]
    [AddCommGroup P] [Module R P] (f : M →ₗ[R] P) {s : Submodule R M}
    (hs1 : (s.map f).FG)
    (hs2 : (s ⊓ LinearMap.ker f).FG) : s.FG := by
  haveI := Classical.decEq R
  haveI := Classical.decEq M
  

Proof state:
R✝ : Type u_1
M✝ : Type u_2
inst✝⁹ : Semiring R✝
inst✝⁸ : AddCommMonoid M✝
inst✝⁷ : Module R✝ M✝
P✝ : Type u_3
inst✝⁶ : AddCommMonoid P✝
inst✝⁵ : Module R✝ P✝
f✝ : M✝ →ₗ[R✝] P✝
R : Type u_4
M : Type u_5
P : Type u_6
inst✝⁴ : Ring R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup P
inst✝ : Module R P
f : M →ₗ[R] P
s : Submodule R M
hs1 : FG (map f s)
hs2 : FG (s ⊓ LinearMap.ker f)
this✝ : DecidableEq R
this : DecidableEq M
⊢ FG s

Next tactic:
haveI := Classical.decEq P
/-- If 0 → M' → M → M'' → 0 is exact and M' and M'' are
finitely generated then so is M. -/
theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Module R M]
    [AddCommGroup P] [Module R P] (f : M →ₗ[R] P) {s : Submodule R M}
    (hs1 : (s.map f).FG)
    (hs2 : (s ⊓ LinearMap.ker f).FG) : s.FG := by
  haveI := Classical.decEq R
  haveI := Classical.decEq M
  haveI := Classical.decEq P
  

Proof state:
R✝ : Type u_1
M✝ : Type u_2
inst✝⁹ : Semiring R✝
inst✝⁸ : AddCommMonoid M✝
inst✝⁷ : Module R✝ M✝
P✝ : Type u_3
inst✝⁶ : AddCommMonoid P✝
inst✝⁵ : Module R✝ P✝
f✝ : M✝ →ₗ[R✝] P✝
R : Type u_4
M : Type u_5
P : Type u_6
inst✝⁴ : Ring R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup P
inst✝ : Module R P
f : M →ₗ[R] P
s : Submodule R M
hs1 : FG (map f s)
hs2 : FG (s ⊓ LinearMap.ker f)
this✝¹ : DecidableEq R
this✝ : DecidableEq M
this : DecidableEq P
⊢ FG s

Next tactic:
cases' hs1 with t1 ht1
/-- If 0 → M' → M → M'' → 0 is exact and M' and M'' are
finitely generated then so is M. -/
theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Module R M]
    [AddCommGroup P] [Module R P] (f : M →ₗ[R] P) {s : Submodule R M}
    (hs1 : (s.map f).FG)
    (hs2 : (s ⊓ LinearMap.ker f).FG) : s.FG := by
  haveI := Classical.decEq R
  haveI := Classical.decEq M
  haveI := Classical.decEq P
  cases' hs1 with t1 ht1
  

Proof state:
case intro
R✝ : Type u_1
M✝ : Type u_2
inst✝⁹ : Semiring R✝
inst✝⁸ : AddCommMonoid M✝
inst✝⁷ : Module R✝ M✝
P✝ : Type u_3
inst✝⁶ : AddCommMonoid P✝
inst✝⁵ : Module R✝ P✝
f✝ : M✝ →ₗ[R✝] P✝
R : Type u_4
M : Type u_5
P : Type u_6
inst✝⁴ : Ring R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup P
inst✝ : Module R P
f : M →ₗ[R] P
s : Submodule R M
hs2 : FG (s ⊓ LinearMap.ker f)
this✝¹ : DecidableEq R
this✝ : DecidableEq M
this : DecidableEq P
t1 : Finset P
ht1 : span R ↑t1 = map f s
⊢ FG s

Next tactic:
cases' hs2 with t2 ht2
/-- If 0 → M' → M → M'' → 0 is exact and M' and M'' are
finitely generated then so is M. -/
theorem fg_of_fg_map_of_fg_inf_ker {R M P : Type*} [Ring R] [AddCommGroup M] [Module R M]
    [AddCommGroup P] [Module R P] (f : M →ₗ[R] P) {s : Submodule R M}
    (hs1 : (s.map f).FG)
    (hs2 : (s ⊓ LinearMap.ker f).FG) : s.FG := by
  haveI := Classical.decEq R
  haveI := Classical.decEq M
  haveI := Classical.decEq P
  cases' hs1 with t1 ht1
  cases' hs2 with t2 ht2
  

Proof state:
case intro.intro
R✝ : Type u_1
M✝ : Type u_2
inst✝⁹ : Semiring R✝
inst✝⁸ : AddCommMonoid M✝
inst✝⁷ : Module R✝ M✝
P✝ : Type u_3
inst✝⁶ : AddCommMonoid P✝
inst✝⁵ : Module R✝ P✝
f✝ : M✝ →ₗ[R✝] P✝
R : Type u_4
M : Type u_5
P : Type u_6
inst✝⁴ : Ring R
inst✝³ : AddCommGroup M
inst✝² : Module R M
inst✝¹ : AddCommGroup P
inst✝ : Module R P
f : M →ₗ[R] P
s : Submodule R M
this✝¹ : DecidableEq R
this✝ : DecidableEq M
this : DecidableEq P
t1 : Finset P
ht1 : span R ↑t1 = map f s
t2 : Finset M
ht2 : span R ↑t2 = s ⊓ LinearMap.ker f
⊢ FG s

Next tactic:
have : ∀ y ∈ t1, ∃ x ∈ s, f x = y := by
    intro y hy
    have : y ∈ s.map f := by
      rw [← ht1]
      exact subset_span hy
    rcases mem_map.1 this with ⟨x, hx1, hx2⟩
    exact ⟨x, hx1, hx2⟩