l3lab/ntp-mathlib huggingface dataset:
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    intro
    simp only [AlgHom.id_apply, AlgEquiv.comp_symm]
  right_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    

Proof state:
case hf
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : σ → R
⊢ ∀ (φ : MvPolynomial σ R), (AlgHom.comp ↑(AlgEquiv.symm f) ↑f) φ = φ

Next tactic:
intro
/-- If two polynomial types over the same coefficient ring `R` are equivalent,
there is a bijection between the types of functions from their variable types to `R`.
-/
noncomputable def comapEquiv (f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R) : (τ → R) ≃ (σ → R) where
  toFun := comap f
  invFun := comap f.symm
  left_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    intro
    simp only [AlgHom.id_apply, AlgEquiv.comp_symm]
  right_inv := by
    intro x
    rw [← comap_comp_apply]
    apply comap_eq_id_of_eq_id
    intro
    

Proof state:
case hf
σ : Type u_1
τ : Type u_2
υ : Type u_3
R : Type u_4
inst✝ : CommSemiring R
f : MvPolynomial σ R ≃ₐ[R] MvPolynomial τ R
x : σ → R
φ✝ : MvPolynomial σ R
⊢ (AlgHom.comp ↑(AlgEquiv.symm f) ↑f) φ✝ = φ✝

Next tactic:
simp only [AlgHom.id_apply, AlgEquiv.symm_comp]
/-- An equivalent expression of `Submonoid.FG` in terms of `Set.Finite` instead of `Finset`. -/
@[to_additive "An equivalent expression of `AddSubmonoid.FG` in terms of `Set.Finite` instead of
`Finset`."]
theorem Submonoid.fg_iff (P : Submonoid M) :
    Submonoid.FG P ↔ ∃ S : Set M, Submonoid.closure S = P ∧ S.Finite :=
  ⟨fun ⟨S, hS⟩ => ⟨S, hS, Finset.finite_toSet S⟩, fun ⟨S, hS, hf⟩ =>
    ⟨Set.Finite.toFinset hf, by 

Proof state:
M : Type u_1
N : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N
P : Submonoid M
x✝ : ∃ S, closure S = P ∧ Set.Finite S
S : Set M
hS : closure S = P
hf : Set.Finite S
⊢ closure ↑(Set.Finite.toFinset hf) = P

Next tactic:
simp [hS]
theorem Submonoid.fg_iff_add_fg (P : Submonoid M) : P.FG ↔ P.toAddSubmonoid.FG :=
  ⟨fun h =>
    let ⟨S, hS, hf⟩ := (Submonoid.fg_iff _).1 h
    (AddSubmonoid.fg_iff _).mpr
      ⟨Additive.toMul ⁻¹' S, by 

Proof state:
M : Type u_1
N : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N
P : Submonoid M
h : FG P
S : Set M
hS : closure S = P
hf : Set.Finite S
⊢ AddSubmonoid.closure (⇑Additive.toMul ⁻¹' S) = toAddSubmonoid P

Next tactic:
simp [← Submonoid.toAddSubmonoid_closure, hS]
theorem Submonoid.fg_iff_add_fg (P : Submonoid M) : P.FG ↔ P.toAddSubmonoid.FG :=
  ⟨fun h =>
    let ⟨S, hS, hf⟩ := (Submonoid.fg_iff _).1 h
    (AddSubmonoid.fg_iff _).mpr
      ⟨Additive.toMul ⁻¹' S, by simp [← Submonoid.toAddSubmonoid_closure, hS], hf⟩,
    fun h =>
    let ⟨T, hT, hf⟩ := (AddSubmonoid.fg_iff _).1 h
    (Submonoid.fg_iff _).mpr
      ⟨Multiplicative.ofAdd ⁻¹' T, by 

Proof state:
M : Type u_1
N : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N
P : Submonoid M
h : AddSubmonoid.FG (toAddSubmonoid P)
T : Set (Additive M)
hT : AddSubmonoid.closure T = toAddSubmonoid P
hf : Set.Finite T
⊢ closure (⇑Multiplicative.ofAdd ⁻¹' T) = P

Next tactic:
simp [← AddSubmonoid.toSubmonoid'_closure, hT]
theorem AddSubmonoid.fg_iff_mul_fg (P : AddSubmonoid N) : P.FG ↔ P.toSubmonoid.FG := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N
P : AddSubmonoid N
⊢ FG P ↔ Submonoid.FG (toSubmonoid P)

Next tactic:
convert (Submonoid.fg_iff_add_fg (toSubmonoid P)).symm
@[to_additive]
instance (priority := 100) Monoid.fg_of_finite [Finite M] : Monoid.FG M := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
inst✝ : Finite M
⊢ FG M

Next tactic:
cases nonempty_fintype M
@[to_additive]
instance (priority := 100) Monoid.fg_of_finite [Finite M] : Monoid.FG M := by
  cases nonempty_fintype M
  

Proof state:
case intro
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
inst✝ : Finite M
val✝ : Fintype M
⊢ FG M

Next tactic:
exact ⟨⟨Finset.univ, by rw [Finset.coe_univ]; exact Submonoid.closure_univ⟩⟩
@[to_additive]
instance (priority := 100) Monoid.fg_of_finite [Finite M] : Monoid.FG M := by
  cases nonempty_fintype M
  exact ⟨⟨Finset.univ, by 

Proof state:
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
inst✝ : Finite M
val✝ : Fintype M
⊢ Submonoid.closure ↑Finset.univ = ⊤

Next tactic:
rw [Finset.coe_univ]
@[to_additive]
instance (priority := 100) Monoid.fg_of_finite [Finite M] : Monoid.FG M := by
  cases nonempty_fintype M
  exact ⟨⟨Finset.univ, by rw [Finset.coe_univ]; 

Proof state:
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
inst✝ : Finite M
val✝ : Fintype M
⊢ Submonoid.closure Set.univ = ⊤

Next tactic:
exact Submonoid.closure_univ
@[to_additive]
theorem Submonoid.FG.map {M' : Type*} [Monoid M'] {P : Submonoid M} (h : P.FG) (e : M →* M') :
    (P.map e).FG := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
h : FG P
e : M →* M'
⊢ FG (Submonoid.map e P)

Next tactic:
classical
    obtain ⟨s, rfl⟩ := h
    exact ⟨s.image e, by rw [Finset.coe_image, MonoidHom.map_mclosure]⟩
@[to_additive]
theorem Submonoid.FG.map {M' : Type*} [Monoid M'] {P : Submonoid M} (h : P.FG) (e : M →* M') :
    (P.map e).FG := by
  classical
    

Proof state:
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
h : FG P
e : M →* M'
⊢ FG (Submonoid.map e P)

Next tactic:
obtain ⟨s, rfl⟩ := h
@[to_additive]
theorem Submonoid.FG.map {M' : Type*} [Monoid M'] {P : Submonoid M} (h : P.FG) (e : M →* M') :
    (P.map e).FG := by
  classical
    obtain ⟨s, rfl⟩ := h
    

Proof state:
case intro
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
e : M →* M'
s : Finset M
⊢ FG (Submonoid.map e (closure ↑s))

Next tactic:
exact ⟨s.image e, by rw [Finset.coe_image, MonoidHom.map_mclosure]⟩
@[to_additive]
theorem Submonoid.FG.map {M' : Type*} [Monoid M'] {P : Submonoid M} (h : P.FG) (e : M →* M') :
    (P.map e).FG := by
  classical
    obtain ⟨s, rfl⟩ := h
    exact ⟨s.image e, by 

Proof state:
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
e : M →* M'
s : Finset M
⊢ closure ↑(Finset.image (⇑e) s) = Submonoid.map e (closure ↑s)

Next tactic:
rw [Finset.coe_image, MonoidHom.map_mclosure]
@[to_additive]
theorem Submonoid.FG.map_injective {M' : Type*} [Monoid M'] {P : Submonoid M} (e : M →* M')
    (he : Function.Injective e) (h : (P.map e).FG) : P.FG := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
e : M →* M'
he : Function.Injective ⇑e
h : FG (Submonoid.map e P)
⊢ FG P

Next tactic:
obtain ⟨s, hs⟩ := h
@[to_additive]
theorem Submonoid.FG.map_injective {M' : Type*} [Monoid M'] {P : Submonoid M} (e : M →* M')
    (he : Function.Injective e) (h : (P.map e).FG) : P.FG := by
  obtain ⟨s, hs⟩ := h
  

Proof state:
case intro
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
e : M →* M'
he : Function.Injective ⇑e
s : Finset M'
hs : closure ↑s = Submonoid.map e P
⊢ FG P

Next tactic:
use s.preimage e (he.injOn _)
@[to_additive]
theorem Submonoid.FG.map_injective {M' : Type*} [Monoid M'] {P : Submonoid M} (e : M →* M')
    (he : Function.Injective e) (h : (P.map e).FG) : P.FG := by
  obtain ⟨s, hs⟩ := h
  use s.preimage e (he.injOn _)
  

Proof state:
case h
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
e : M →* M'
he : Function.Injective ⇑e
s : Finset M'
hs : closure ↑s = Submonoid.map e P
⊢ closure ↑(Finset.preimage s ⇑e (_ : Set.InjOn (⇑e) (⇑e ⁻¹' ↑s))) = P

Next tactic:
apply Submonoid.map_injective_of_injective he
@[to_additive]
theorem Submonoid.FG.map_injective {M' : Type*} [Monoid M'] {P : Submonoid M} (e : M →* M')
    (he : Function.Injective e) (h : (P.map e).FG) : P.FG := by
  obtain ⟨s, hs⟩ := h
  use s.preimage e (he.injOn _)
  apply Submonoid.map_injective_of_injective he
  

Proof state:
case h.a
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
e : M →* M'
he : Function.Injective ⇑e
s : Finset M'
hs : closure ↑s = Submonoid.map e P
⊢ Submonoid.map e (closure ↑(Finset.preimage s ⇑e (_ : Set.InjOn (⇑e) (⇑e ⁻¹' ↑s)))) = Submonoid.map e P

Next tactic:
rw [← hs, MonoidHom.map_mclosure e, Finset.coe_preimage]
@[to_additive]
theorem Submonoid.FG.map_injective {M' : Type*} [Monoid M'] {P : Submonoid M} (e : M →* M')
    (he : Function.Injective e) (h : (P.map e).FG) : P.FG := by
  obtain ⟨s, hs⟩ := h
  use s.preimage e (he.injOn _)
  apply Submonoid.map_injective_of_injective he
  rw [← hs, MonoidHom.map_mclosure e, Finset.coe_preimage]
  

Proof state:
case h.a
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
e : M →* M'
he : Function.Injective ⇑e
s : Finset M'
hs : closure ↑s = Submonoid.map e P
⊢ closure (⇑e '' (⇑e ⁻¹' ↑s)) = closure ↑s

Next tactic:
congr
@[to_additive]
theorem Submonoid.FG.map_injective {M' : Type*} [Monoid M'] {P : Submonoid M} (e : M →* M')
    (he : Function.Injective e) (h : (P.map e).FG) : P.FG := by
  obtain ⟨s, hs⟩ := h
  use s.preimage e (he.injOn _)
  apply Submonoid.map_injective_of_injective he
  rw [← hs, MonoidHom.map_mclosure e, Finset.coe_preimage]
  congr
  

Proof state:
case h.a.e_s
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
e : M →* M'
he : Function.Injective ⇑e
s : Finset M'
hs : closure ↑s = Submonoid.map e P
⊢ ⇑e '' (⇑e ⁻¹' ↑s) = ↑s

Next tactic:
rw [Set.image_preimage_eq_iff, ← MonoidHom.coe_mrange e, ← Submonoid.closure_le, hs,
      MonoidHom.mrange_eq_map e]
@[to_additive]
theorem Submonoid.FG.map_injective {M' : Type*} [Monoid M'] {P : Submonoid M} (e : M →* M')
    (he : Function.Injective e) (h : (P.map e).FG) : P.FG := by
  obtain ⟨s, hs⟩ := h
  use s.preimage e (he.injOn _)
  apply Submonoid.map_injective_of_injective he
  rw [← hs, MonoidHom.map_mclosure e, Finset.coe_preimage]
  congr
  rw [Set.image_preimage_eq_iff, ← MonoidHom.coe_mrange e, ← Submonoid.closure_le, hs,
      MonoidHom.mrange_eq_map e]
  

Proof state:
case h.a.e_s
M : Type u_1
N : Type u_2
inst✝² : Monoid M
inst✝¹ : AddMonoid N
M' : Type u_3
inst✝ : Monoid M'
P : Submonoid M
e : M →* M'
he : Function.Injective ⇑e
s : Finset M'
hs : closure ↑s = Submonoid.map e P
⊢ Submonoid.map e P ≤ Submonoid.map e ⊤

Next tactic:
exact Submonoid.monotone_map le_top
@[to_additive (attr := simp)]
theorem Monoid.fg_iff_submonoid_fg (N : Submonoid M) : Monoid.FG N ↔ N.FG := by
  

Proof state:
M : Type u_1
N✝ : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N✝
N : Submonoid M
⊢ FG ↥N ↔ Submonoid.FG N

Next tactic:
conv_rhs => rw [← N.range_subtype, MonoidHom.mrange_eq_map]
@[to_additive (attr := simp)]
theorem Monoid.fg_iff_submonoid_fg (N : Submonoid M) : Monoid.FG N ↔ N.FG := by
  conv_rhs => 

Proof state:
M : Type u_1
N✝ : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N✝
N : Submonoid M
| Submonoid.FG N

Next tactic:
rw [← N.range_subtype, MonoidHom.mrange_eq_map]
@[to_additive (attr := simp)]
theorem Monoid.fg_iff_submonoid_fg (N : Submonoid M) : Monoid.FG N ↔ N.FG := by
  conv_rhs => rw [← N.range_subtype, MonoidHom.mrange_eq_map]
  

Proof state:
M : Type u_1
N✝ : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N✝
N : Submonoid M
⊢ FG ↥N ↔ Submonoid.FG (Submonoid.map (Submonoid.subtype N) ⊤)

Next tactic:
exact ⟨fun h => h.out.map N.subtype, fun h => ⟨h.map_injective N.subtype Subtype.coe_injective⟩⟩
@[to_additive]
theorem Monoid.fg_of_surjective {M' : Type*} [Monoid M'] [Monoid.FG M] (f : M →* M')
    (hf : Function.Surjective f) : Monoid.FG M' := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
M' : Type u_3
inst✝¹ : Monoid M'
inst✝ : FG M
f : M →* M'
hf : Function.Surjective ⇑f
⊢ FG M'

Next tactic:
classical
    obtain ⟨s, hs⟩ := Monoid.fg_def.mp ‹_›
    use s.image f
    rwa [Finset.coe_image, ← MonoidHom.map_mclosure, hs, ← MonoidHom.mrange_eq_map,
      MonoidHom.mrange_top_iff_surjective]
@[to_additive]
theorem Monoid.fg_of_surjective {M' : Type*} [Monoid M'] [Monoid.FG M] (f : M →* M')
    (hf : Function.Surjective f) : Monoid.FG M' := by
  classical
    

Proof state:
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
M' : Type u_3
inst✝¹ : Monoid M'
inst✝ : FG M
f : M →* M'
hf : Function.Surjective ⇑f
⊢ FG M'

Next tactic:
obtain ⟨s, hs⟩ := Monoid.fg_def.mp ‹_›
@[to_additive]
theorem Monoid.fg_of_surjective {M' : Type*} [Monoid M'] [Monoid.FG M] (f : M →* M')
    (hf : Function.Surjective f) : Monoid.FG M' := by
  classical
    obtain ⟨s, hs⟩ := Monoid.fg_def.mp ‹_›
    

Proof state:
case intro
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
M' : Type u_3
inst✝¹ : Monoid M'
inst✝ : FG M
f : M →* M'
hf : Function.Surjective ⇑f
s : Finset M
hs : Submonoid.closure ↑s = ⊤
⊢ FG M'

Next tactic:
use s.image f
@[to_additive]
theorem Monoid.fg_of_surjective {M' : Type*} [Monoid M'] [Monoid.FG M] (f : M →* M')
    (hf : Function.Surjective f) : Monoid.FG M' := by
  classical
    obtain ⟨s, hs⟩ := Monoid.fg_def.mp ‹_›
    use s.image f
    

Proof state:
case h
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
M' : Type u_3
inst✝¹ : Monoid M'
inst✝ : FG M
f : M →* M'
hf : Function.Surjective ⇑f
s : Finset M
hs : Submonoid.closure ↑s = ⊤
⊢ Submonoid.closure ↑(Finset.image (⇑f) s) = ⊤

Next tactic:
rwa [Finset.coe_image, ← MonoidHom.map_mclosure, hs, ← MonoidHom.mrange_eq_map,
      MonoidHom.mrange_top_iff_surjective]
@[to_additive]
instance Monoid.closure_finset_fg (s : Finset M) : Monoid.FG (Submonoid.closure (s : Set M)) := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N
s : Finset M
⊢ FG ↥(Submonoid.closure ↑s)

Next tactic:
refine' ⟨⟨s.preimage Subtype.val (Subtype.coe_injective.injOn _), _⟩⟩
@[to_additive]
instance Monoid.closure_finset_fg (s : Finset M) : Monoid.FG (Submonoid.closure (s : Set M)) := by
  refine' ⟨⟨s.preimage Subtype.val (Subtype.coe_injective.injOn _), _⟩⟩
  

Proof state:
M : Type u_1
N : Type u_2
inst✝¹ : Monoid M
inst✝ : AddMonoid N
s : Finset M
⊢ Submonoid.closure ↑(Finset.preimage s Subtype.val (_ : Set.InjOn (fun a => ↑a) (Subtype.val ⁻¹' ↑s))) = ⊤

Next tactic:
rw [Finset.coe_preimage, Submonoid.closure_closure_coe_preimage]
/-- An equivalent expression of `Subgroup.FG` in terms of `Set.Finite` instead of `Finset`. -/
@[to_additive "An equivalent expression of `AddSubgroup.fg` in terms of `Set.Finite` instead of
`Finset`."]
theorem Subgroup.fg_iff (P : Subgroup G) :
    Subgroup.FG P ↔ ∃ S : Set G, Subgroup.closure S = P ∧ S.Finite :=
  ⟨fun ⟨S, hS⟩ => ⟨S, hS, Finset.finite_toSet S⟩, fun ⟨S, hS, hf⟩ =>
    ⟨Set.Finite.toFinset hf, by 

Proof state:
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
x✝ : ∃ S, closure S = P ∧ Set.Finite S
S : Set G
hS : closure S = P
hf : Set.Finite S
⊢ closure ↑(Set.Finite.toFinset hf) = P

Next tactic:
simp [hS]
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
⊢ FG P ↔ Submonoid.FG P.toSubmonoid

Next tactic:
constructor
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · 

Proof state:
case mp
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
⊢ FG P → Submonoid.FG P.toSubmonoid

Next tactic:
rintro ⟨S, rfl⟩
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    

Proof state:
case mp.intro
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
S : Finset G
⊢ Submonoid.FG (closure ↑S).toSubmonoid

Next tactic:
rw [Submonoid.fg_iff]
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    

Proof state:
case mp.intro
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
S : Finset G
⊢ ∃ S_1, Submonoid.closure S_1 = (closure ↑S).toSubmonoid ∧ Set.Finite S_1

Next tactic:
refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
    

Proof state:
case mp.intro
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
S : Finset G
⊢ Submonoid.closure (↑S ∪ (↑S)⁻¹) = (closure ↑S).toSubmonoid

Next tactic:
exact (Subgroup.closure_toSubmonoid _).symm
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
    exact (Subgroup.closure_toSubmonoid _).symm
  · 

Proof state:
case mpr
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
⊢ Submonoid.FG P.toSubmonoid → FG P

Next tactic:
rintro ⟨S, hS⟩
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
    exact (Subgroup.closure_toSubmonoid _).symm
  · rintro ⟨S, hS⟩
    

Proof state:
case mpr.intro
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
S : Finset G
hS : Submonoid.closure ↑S = P.toSubmonoid
⊢ FG P

Next tactic:
refine' ⟨S, le_antisymm _ _⟩
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
    exact (Subgroup.closure_toSubmonoid _).symm
  · rintro ⟨S, hS⟩
    refine' ⟨S, le_antisymm _ _⟩
    · 

Proof state:
case mpr.intro.refine'_1
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
S : Finset G
hS : Submonoid.closure ↑S = P.toSubmonoid
⊢ closure ↑S ≤ P

Next tactic:
rw [Subgroup.closure_le, ← Subgroup.coe_toSubmonoid, ← hS]
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
    exact (Subgroup.closure_toSubmonoid _).symm
  · rintro ⟨S, hS⟩
    refine' ⟨S, le_antisymm _ _⟩
    · rw [Subgroup.closure_le, ← Subgroup.coe_toSubmonoid, ← hS]
      

Proof state:
case mpr.intro.refine'_1
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
S : Finset G
hS : Submonoid.closure ↑S = P.toSubmonoid
⊢ ↑S ⊆ ↑(Submonoid.closure ↑S)

Next tactic:
exact Submonoid.subset_closure
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
    exact (Subgroup.closure_toSubmonoid _).symm
  · rintro ⟨S, hS⟩
    refine' ⟨S, le_antisymm _ _⟩
    · rw [Subgroup.closure_le, ← Subgroup.coe_toSubmonoid, ← hS]
      exact Submonoid.subset_closure
    · 

Proof state:
case mpr.intro.refine'_2
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
S : Finset G
hS : Submonoid.closure ↑S = P.toSubmonoid
⊢ P ≤ closure ↑S

Next tactic:
rw [← Subgroup.toSubmonoid_le, ← hS, Submonoid.closure_le]
/-- A subgroup is finitely generated if and only if it is finitely generated as a submonoid. -/
@[to_additive "An additive subgroup is finitely generated if
and only if it is finitely generated as an additive submonoid."]
theorem Subgroup.fg_iff_submonoid_fg (P : Subgroup G) : P.FG ↔ P.toSubmonoid.FG := by
  constructor
  · rintro ⟨S, rfl⟩
    rw [Submonoid.fg_iff]
    refine' ⟨S ∪ S⁻¹, _, S.finite_toSet.union S.finite_toSet.inv⟩
    exact (Subgroup.closure_toSubmonoid _).symm
  · rintro ⟨S, hS⟩
    refine' ⟨S, le_antisymm _ _⟩
    · rw [Subgroup.closure_le, ← Subgroup.coe_toSubmonoid, ← hS]
      exact Submonoid.subset_closure
    · rw [← Subgroup.toSubmonoid_le, ← hS, Submonoid.closure_le]
      

Proof state:
case mpr.intro.refine'_2
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
S : Finset G
hS : Submonoid.closure ↑S = P.toSubmonoid
⊢ ↑S ⊆ ↑(closure ↑S).toSubmonoid

Next tactic:
exact Subgroup.subset_closure
theorem Subgroup.fg_iff_add_fg (P : Subgroup G) : P.FG ↔ P.toAddSubgroup.FG := by
  

Proof state:
M : Type u_1
N : Type u_2
inst✝³ : Monoid M
inst✝² : AddMonoid N
G : Type u_3
H : Type u_4
inst✝¹ : Group G
inst✝ : AddGroup H
P : Subgroup G
⊢ FG P ↔ AddSubgroup.FG (toAddSubgroup P)

Next tactic:
rw [Subgroup.fg_iff_submonoid_fg, AddSubgroup.fg_iff_addSubmonoid_fg]