l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
⊢ Nat.card G ∣ Monoid.exponent G ^ Group.rank G

Next tactic:
rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
⊢ Nat.card G ∣ ∏ _x : { x // x ∈ S }, Monoid.exponent G

Next tactic:
let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
⊢ Nat.card G ∣ ∏ _x : { x // x ∈ S }, Monoid.exponent G

Next tactic:
have hf : Function.Surjective f := by
    rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
    exact fun g hg => ⟨Pi.mulSingle ⟨g, hg⟩ ⟨g, mem_zpowers g⟩, noncommPiCoprod_mulSingle _ _⟩
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  have hf : Function.Surjective f := by
    

Proof state:
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
⊢ Function.Surjective ⇑f

Next tactic:
rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  have hf : Function.Surjective f := by
    rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
    

Proof state:
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
⊢ ↑S ⊆ ↑(MonoidHom.range f)

Next tactic:
exact fun g hg => ⟨Pi.mulSingle ⟨g, hg⟩ ⟨g, mem_zpowers g⟩, noncommPiCoprod_mulSingle _ _⟩
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  have hf : Function.Surjective f := by
    rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
    exact fun g hg => ⟨Pi.mulSingle ⟨g, hg⟩ ⟨g, mem_zpowers g⟩, noncommPiCoprod_mulSingle _ _⟩
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
hf : Function.Surjective ⇑f
⊢ Nat.card G ∣ ∏ _x : { x // x ∈ S }, Monoid.exponent G

Next tactic:
replace hf := nat_card_dvd_of_surjective f hf
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  have hf : Function.Surjective f := by
    rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
    exact fun g hg => ⟨Pi.mulSingle ⟨g, hg⟩ ⟨g, mem_zpowers g⟩, noncommPiCoprod_mulSingle _ _⟩
  replace hf := nat_card_dvd_of_surjective f hf
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
hf : Nat.card G ∣ Nat.card ((g : { x // x ∈ S }) → ↥(zpowers ↑g))
⊢ Nat.card G ∣ ∏ _x : { x // x ∈ S }, Monoid.exponent G

Next tactic:
rw [Nat.card_pi] at hf
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  have hf : Function.Surjective f := by
    rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
    exact fun g hg => ⟨Pi.mulSingle ⟨g, hg⟩ ⟨g, mem_zpowers g⟩, noncommPiCoprod_mulSingle _ _⟩
  replace hf := nat_card_dvd_of_surjective f hf
  rw [Nat.card_pi] at hf
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
hf : Nat.card G ∣ ∏ a : { x // x ∈ S }, Nat.card ↥(zpowers ↑a)
⊢ Nat.card G ∣ ∏ _x : { x // x ∈ S }, Monoid.exponent G

Next tactic:
refine' hf.trans (Finset.prod_dvd_prod_of_dvd _ _ fun g _ => _)
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  have hf : Function.Surjective f := by
    rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
    exact fun g hg => ⟨Pi.mulSingle ⟨g, hg⟩ ⟨g, mem_zpowers g⟩, noncommPiCoprod_mulSingle _ _⟩
  replace hf := nat_card_dvd_of_surjective f hf
  rw [Nat.card_pi] at hf
  refine' hf.trans (Finset.prod_dvd_prod_of_dvd _ _ fun g _ => _)
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
hf : Nat.card G ∣ ∏ a : { x // x ∈ S }, Nat.card ↥(zpowers ↑a)
g : { x // x ∈ S }
x✝ : g ∈ Finset.univ
⊢ Nat.card ↥(zpowers ↑g) ∣ Monoid.exponent G

Next tactic:
rw [Nat.card_zpowers]
@[to_additive]
theorem card_dvd_exponent_pow_rank : Nat.card G ∣ Monoid.exponent G ^ Group.rank G := by
  obtain ⟨S, hS1, hS2⟩ := Group.rank_spec G
  rw [← hS1, ← Fintype.card_coe, ← Finset.card_univ, ← Finset.prod_const]
  let f : (∀ g : S, zpowers (g : G)) →* G := noncommPiCoprod fun s t _ x y _ _ => mul_comm x _
  have hf : Function.Surjective f := by
    rw [← MonoidHom.range_top_iff_surjective, eq_top_iff, ← hS2, closure_le]
    exact fun g hg => ⟨Pi.mulSingle ⟨g, hg⟩ ⟨g, mem_zpowers g⟩, noncommPiCoprod_mulSingle _ _⟩
  replace hf := nat_card_dvd_of_surjective f hf
  rw [Nat.card_pi] at hf
  refine' hf.trans (Finset.prod_dvd_prod_of_dvd _ _ fun g _ => _)
  rw [Nat.card_zpowers]
  

Proof state:
case intro.intro
G : Type u
inst✝¹ : CommGroup G
inst✝ : Group.FG G
S : Finset G
hS1 : Finset.card S = Group.rank G
hS2 : closure ↑S = ⊤
f : ((g : { x // x ∈ S }) → ↥(zpowers ↑g)) →* G :=
  noncommPiCoprod (_ : ∀ (s t : { x // x ∈ S }), s ≠ t → ∀ (x y : G), x ∈ zpowers ↑s → y ∈ zpowers ↑t → x * y = y * x)
hf : Nat.card G ∣ ∏ a : { x // x ∈ S }, Nat.card ↥(zpowers ↑a)
g : { x // x ∈ S }
x✝ : g ∈ Finset.univ
⊢ orderOf ↑g ∣ Monoid.exponent G

Next tactic:
exact Monoid.order_dvd_exponent (g : G)
@[to_additive]
theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoid (M i)] {j : ι}
    (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by
  

Proof state:
G : Type u
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
j : ι
hj : exponent (M j) = 0
⊢ exponent ((i : ι) → M i) = 0

Next tactic:
rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢
@[to_additive]
theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoid (M i)] {j : ι}
    (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by
  rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢
  

Proof state:
G : Type u
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
j : ι
hj : ¬∃ n, 0 < n ∧ ∀ (g : M j), g ^ n = 1
⊢ ¬∃ n, 0 < n ∧ ∀ (g : (i : ι) → M i), g ^ n = 1

Next tactic:
push_neg at hj ⊢
@[to_additive]
theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoid (M i)] {j : ι}
    (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by
  rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢
  push_neg at hj ⊢
  

Proof state:
G : Type u
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
j : ι
hj : ∀ (n : ℕ), 0 < n → ∃ g, g ^ n ≠ 1
⊢ ∀ (n : ℕ), 0 < n → ∃ g, g ^ n ≠ 1

Next tactic:
peel hj with _ n hn
@[to_additive]
theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoid (M i)] {j : ι}
    (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by
  rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢
  push_neg at hj ⊢
  peel hj with _ n hn
  

Proof state:
case h.h
G : Type u
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
j : ι
hj : ∀ (n : ℕ), 0 < n → ∃ g, g ^ n ≠ 1
n : ℕ
hn : 0 < n
this : ∃ g, g ^ n ≠ 1
⊢ ∃ g, g ^ n ≠ 1

Next tactic:
obtain ⟨m, hm⟩ := this
@[to_additive]
theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoid (M i)] {j : ι}
    (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by
  rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢
  push_neg at hj ⊢
  peel hj with _ n hn
  obtain ⟨m, hm⟩ := this
  

Proof state:
case h.h.intro
G : Type u
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
j : ι
hj : ∀ (n : ℕ), 0 < n → ∃ g, g ^ n ≠ 1
n : ℕ
hn : 0 < n
m : M j
hm : m ^ n ≠ 1
⊢ ∃ g, g ^ n ≠ 1

Next tactic:
refine ⟨Pi.mulSingle j m, fun h ↦ hm ?_⟩
@[to_additive]
theorem Monoid.exponent_pi_eq_zero {ι : Type*} {M : ι → Type*} [∀ i, Monoid (M i)] {j : ι}
    (hj : exponent (M j) = 0) : exponent ((i : ι) → M i) = 0 := by
  rw [@exponent_eq_zero_iff, ExponentExists] at hj ⊢
  push_neg at hj ⊢
  peel hj with _ n hn
  obtain ⟨m, hm⟩ := this
  refine ⟨Pi.mulSingle j m, fun h ↦ hm ?_⟩
  

Proof state:
case h.h.intro
G : Type u
ι : Type u_1
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
j : ι
hj : ∀ (n : ℕ), 0 < n → ∃ g, g ^ n ≠ 1
n : ℕ
hn : 0 < n
m : M j
hm : m ^ n ≠ 1
h : Pi.mulSingle j m ^ n = 1
⊢ m ^ n = 1

Next tactic:
simpa using congr_fun h j
/-- If `f : M₁ →⋆ M₂` is surjective, then the exponent of `M₂` divides the exponent of `M₁`. -/
@[to_additive]
theorem MonoidHom.exponent_dvd {F M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] [MonoidHomClass F M₁ M₂]
    {f : F} (hf : Function.Surjective f) : exponent M₂ ∣ exponent M₁ := by
  

Proof state:
G : Type u
F : Type u_1
M₁ : Type u_2
M₂ : Type u_3
inst✝² : Monoid M₁
inst✝¹ : Monoid M₂
inst✝ : MonoidHomClass F M₁ M₂
f : F
hf : Function.Surjective ⇑f
⊢ exponent M₂ ∣ exponent M₁

Next tactic:
refine Monoid.exponent_dvd_of_forall_pow_eq_one M₂ _ fun m₂ ↦ ?_
/-- If `f : M₁ →⋆ M₂` is surjective, then the exponent of `M₂` divides the exponent of `M₁`. -/
@[to_additive]
theorem MonoidHom.exponent_dvd {F M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] [MonoidHomClass F M₁ M₂]
    {f : F} (hf : Function.Surjective f) : exponent M₂ ∣ exponent M₁ := by
  refine Monoid.exponent_dvd_of_forall_pow_eq_one M₂ _ fun m₂ ↦ ?_
  

Proof state:
G : Type u
F : Type u_1
M₁ : Type u_2
M₂ : Type u_3
inst✝² : Monoid M₁
inst✝¹ : Monoid M₂
inst✝ : MonoidHomClass F M₁ M₂
f : F
hf : Function.Surjective ⇑f
m₂ : M₂
⊢ m₂ ^ exponent M₁ = 1

Next tactic:
obtain ⟨m₁, rfl⟩ := hf m₂
/-- If `f : M₁ →⋆ M₂` is surjective, then the exponent of `M₂` divides the exponent of `M₁`. -/
@[to_additive]
theorem MonoidHom.exponent_dvd {F M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] [MonoidHomClass F M₁ M₂]
    {f : F} (hf : Function.Surjective f) : exponent M₂ ∣ exponent M₁ := by
  refine Monoid.exponent_dvd_of_forall_pow_eq_one M₂ _ fun m₂ ↦ ?_
  obtain ⟨m₁, rfl⟩ := hf m₂
  

Proof state:
case intro
G : Type u
F : Type u_1
M₁ : Type u_2
M₂ : Type u_3
inst✝² : Monoid M₁
inst✝¹ : Monoid M₂
inst✝ : MonoidHomClass F M₁ M₂
f : F
hf : Function.Surjective ⇑f
m₁ : M₁
⊢ f m₁ ^ exponent M₁ = 1

Next tactic:
rw [← map_pow, pow_exponent_eq_one, map_one]
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  

Proof state:
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
⊢ exponent ((i : ι) → M i) = Finset.lcm univ fun x => exponent (M x)

Next tactic:
refine dvd_antisymm ?_ ?_
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  refine dvd_antisymm ?_ ?_
  · 

Proof state:
case refine_1
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
⊢ exponent ((i : ι) → M i) ∣ Finset.lcm univ fun x => exponent (M x)

Next tactic:
refine exponent_dvd_of_forall_pow_eq_one _ _ fun m ↦ ?_
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  refine dvd_antisymm ?_ ?_
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun m ↦ ?_
    

Proof state:
case refine_1
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
m : (i : ι) → M i
⊢ (m ^ Finset.lcm univ fun x => exponent (M x)) = 1

Next tactic:
ext i
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  refine dvd_antisymm ?_ ?_
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun m ↦ ?_
    ext i
    

Proof state:
case refine_1.h
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
m : (i : ι) → M i
i : ι
⊢ (m ^ Finset.lcm univ fun x => exponent (M x)) i = OfNat.ofNat 1 i

Next tactic:
rw [Pi.pow_apply, Pi.one_apply, ← orderOf_dvd_iff_pow_eq_one]
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  refine dvd_antisymm ?_ ?_
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun m ↦ ?_
    ext i
    rw [Pi.pow_apply, Pi.one_apply, ← orderOf_dvd_iff_pow_eq_one]
    

Proof state:
case refine_1.h
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
m : (i : ι) → M i
i : ι
⊢ orderOf (m i) ∣ Finset.lcm univ fun x => exponent (M x)

Next tactic:
apply dvd_trans (Monoid.order_dvd_exponent (m i))
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  refine dvd_antisymm ?_ ?_
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun m ↦ ?_
    ext i
    rw [Pi.pow_apply, Pi.one_apply, ← orderOf_dvd_iff_pow_eq_one]
    apply dvd_trans (Monoid.order_dvd_exponent (m i))
    

Proof state:
case refine_1.h
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
m : (i : ι) → M i
i : ι
⊢ exponent (M i) ∣ Finset.lcm univ fun x => exponent (M x)

Next tactic:
exact Finset.dvd_lcm (mem_univ i)
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  refine dvd_antisymm ?_ ?_
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun m ↦ ?_
    ext i
    rw [Pi.pow_apply, Pi.one_apply, ← orderOf_dvd_iff_pow_eq_one]
    apply dvd_trans (Monoid.order_dvd_exponent (m i))
    exact Finset.dvd_lcm (mem_univ i)
  · 

Proof state:
case refine_2
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
⊢ (Finset.lcm univ fun x => exponent (M x)) ∣ exponent ((i : ι) → M i)

Next tactic:
apply Finset.lcm_dvd fun i _ ↦ ?_
/-- The exponent of finite product of monoids is the `Finset.lcm` of the exponents of the
constituent monoids. -/
@[to_additive "The exponent of finite product of additive monoids is the `Finset.lcm` of the
exponents of the constituent additive monoids."]
theorem Monoid.exponent_pi {ι : Type*} [Fintype ι] {M : ι → Type*} [∀ i, Monoid (M i)] :
    exponent ((i : ι) → M i) = lcm univ (exponent <| M ·) := by
  refine dvd_antisymm ?_ ?_
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun m ↦ ?_
    ext i
    rw [Pi.pow_apply, Pi.one_apply, ← orderOf_dvd_iff_pow_eq_one]
    apply dvd_trans (Monoid.order_dvd_exponent (m i))
    exact Finset.dvd_lcm (mem_univ i)
  · apply Finset.lcm_dvd fun i _ ↦ ?_
    

Proof state:
G : Type u
ι : Type u_1
inst✝¹ : Fintype ι
M : ι → Type u_2
inst✝ : (i : ι) → Monoid (M i)
i : ι
x✝ : i ∈ univ
⊢ exponent (M i) ∣ exponent ((i : ι) → M i)

Next tactic:
exact MonoidHom.exponent_dvd (f := Pi.evalMonoidHom (M ·) i) (Function.surjective_eval i)
/-- The exponent of product of two monoids is the `lcm` of the exponents of the
individuaul monoids. -/
@[to_additive AddMonoid.exponent_prod "The exponent of product of two additive monoids is the `lcm`
of the exponents of the individuaul additive monoids."]
theorem Monoid.exponent_prod {M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] :
    exponent (M₁ × M₂) = lcm (exponent M₁) (exponent M₂) := by
  

Proof state:
G : Type u
M₁ : Type u_1
M₂ : Type u_2
inst✝¹ : Monoid M₁
inst✝ : Monoid M₂
⊢ exponent (M₁ × M₂) = GCDMonoid.lcm (exponent M₁) (exponent M₂)

Next tactic:
refine dvd_antisymm ?_ (lcm_dvd ?_ ?_)
/-- The exponent of product of two monoids is the `lcm` of the exponents of the
individuaul monoids. -/
@[to_additive AddMonoid.exponent_prod "The exponent of product of two additive monoids is the `lcm`
of the exponents of the individuaul additive monoids."]
theorem Monoid.exponent_prod {M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] :
    exponent (M₁ × M₂) = lcm (exponent M₁) (exponent M₂) := by
  refine dvd_antisymm ?_ (lcm_dvd ?_ ?_)
  · 

Proof state:
case refine_1
G : Type u
M₁ : Type u_1
M₂ : Type u_2
inst✝¹ : Monoid M₁
inst✝ : Monoid M₂
⊢ exponent (M₁ × M₂) ∣ GCDMonoid.lcm (exponent M₁) (exponent M₂)

Next tactic:
refine exponent_dvd_of_forall_pow_eq_one _ _ fun g ↦ ?_
/-- The exponent of product of two monoids is the `lcm` of the exponents of the
individuaul monoids. -/
@[to_additive AddMonoid.exponent_prod "The exponent of product of two additive monoids is the `lcm`
of the exponents of the individuaul additive monoids."]
theorem Monoid.exponent_prod {M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] :
    exponent (M₁ × M₂) = lcm (exponent M₁) (exponent M₂) := by
  refine dvd_antisymm ?_ (lcm_dvd ?_ ?_)
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun g ↦ ?_
    

Proof state:
case refine_1
G : Type u
M₁ : Type u_1
M₂ : Type u_2
inst✝¹ : Monoid M₁
inst✝ : Monoid M₂
g : M₁ × M₂
⊢ g ^ GCDMonoid.lcm (exponent M₁) (exponent M₂) = 1

Next tactic:
ext1
/-- The exponent of product of two monoids is the `lcm` of the exponents of the
individuaul monoids. -/
@[to_additive AddMonoid.exponent_prod "The exponent of product of two additive monoids is the `lcm`
of the exponents of the individuaul additive monoids."]
theorem Monoid.exponent_prod {M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] :
    exponent (M₁ × M₂) = lcm (exponent M₁) (exponent M₂) := by
  refine dvd_antisymm ?_ (lcm_dvd ?_ ?_)
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun g ↦ ?_
    ext1
    · 

Proof state:
case refine_1.a
G : Type u
M₁ : Type u_1
M₂ : Type u_2
inst✝¹ : Monoid M₁
inst✝ : Monoid M₂
g : M₁ × M₂
⊢ (g ^ GCDMonoid.lcm (exponent M₁) (exponent M₂)).1 = 1.1

Next tactic:
rw [Prod.pow_fst, Prod.fst_one, ← orderOf_dvd_iff_pow_eq_one]
/-- The exponent of product of two monoids is the `lcm` of the exponents of the
individuaul monoids. -/
@[to_additive AddMonoid.exponent_prod "The exponent of product of two additive monoids is the `lcm`
of the exponents of the individuaul additive monoids."]
theorem Monoid.exponent_prod {M₁ M₂ : Type*} [Monoid M₁] [Monoid M₂] :
    exponent (M₁ × M₂) = lcm (exponent M₁) (exponent M₂) := by
  refine dvd_antisymm ?_ (lcm_dvd ?_ ?_)
  · refine exponent_dvd_of_forall_pow_eq_one _ _ fun g ↦ ?_
    ext1
    · rw [Prod.pow_fst, Prod.fst_one, ← orderOf_dvd_iff_pow_eq_one]
      

Proof state:
case refine_1.a
G : Type u
M₁ : Type u_1
M₂ : Type u_2
inst✝¹ : Monoid M₁
inst✝ : Monoid M₂
g : M₁ × M₂
⊢ orderOf g.1 ∣ GCDMonoid.lcm (exponent M₁) (exponent M₂)

Next tactic:
exact dvd_trans (Monoid.order_dvd_exponent (g.1)) <| dvd_lcm_left _ _