l3lab/ntp-mathlib huggingface dataset:
@[to_additive (attr := simp) additiveEnergy_univ_left]
theorem multiplicativeEnergy_univ_left :
    multiplicativeEnergy univ t = Fintype.card α * t.card ^ 2 := by
  simp only [multiplicativeEnergy, univ_product_univ, Fintype.card, sq, ← card_product]
  let f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
  have : (↑((univ : Finset α) ×ˢ t ×ˢ t) : Set (α × α × α)).InjOn f := by
    rintro ⟨a₁, b₁, c₁⟩ _ ⟨a₂, b₂, c₂⟩ h₂ h
    simp_rw [Prod.ext_iff] at h
    obtain ⟨h, rfl, rfl⟩ := h
    rw [mul_right_cancel h.1]
  rw [← card_image_of_injOn this]
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
⊢ card (filter (fun x => x.1.1 * x.2.1 = x.1.2 * x.2.2) (univ ×ˢ t ×ˢ t)) = card (image f (univ ×ˢ t ×ˢ t))

Next tactic:
congr with a
@[to_additive (attr := simp) additiveEnergy_univ_left]
theorem multiplicativeEnergy_univ_left :
    multiplicativeEnergy univ t = Fintype.card α * t.card ^ 2 := by
  simp only [multiplicativeEnergy, univ_product_univ, Fintype.card, sq, ← card_product]
  let f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
  have : (↑((univ : Finset α) ×ˢ t ×ˢ t) : Set (α × α × α)).InjOn f := by
    rintro ⟨a₁, b₁, c₁⟩ _ ⟨a₂, b₂, c₂⟩ h₂ h
    simp_rw [Prod.ext_iff] at h
    obtain ⟨h, rfl, rfl⟩ := h
    rw [mul_right_cancel h.1]
  rw [← card_image_of_injOn this]
  congr with a
  

Proof state:
case e_s.a
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
a : (α × α) × α × α
⊢ a ∈ filter (fun x => x.1.1 * x.2.1 = x.1.2 * x.2.2) (univ ×ˢ t ×ˢ t) ↔ a ∈ image f (univ ×ˢ t ×ˢ t)

Next tactic:
simp only [mem_filter, mem_product, mem_univ, true_and_iff, mem_image, exists_prop,
    Prod.exists]
@[to_additive (attr := simp) additiveEnergy_univ_left]
theorem multiplicativeEnergy_univ_left :
    multiplicativeEnergy univ t = Fintype.card α * t.card ^ 2 := by
  simp only [multiplicativeEnergy, univ_product_univ, Fintype.card, sq, ← card_product]
  let f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
  have : (↑((univ : Finset α) ×ˢ t ×ˢ t) : Set (α × α × α)).InjOn f := by
    rintro ⟨a₁, b₁, c₁⟩ _ ⟨a₂, b₂, c₂⟩ h₂ h
    simp_rw [Prod.ext_iff] at h
    obtain ⟨h, rfl, rfl⟩ := h
    rw [mul_right_cancel h.1]
  rw [← card_image_of_injOn this]
  congr with a
  simp only [mem_filter, mem_product, mem_univ, true_and_iff, mem_image, exists_prop,
    Prod.exists]
  

Proof state:
case e_s.a
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
a : (α × α) × α × α
⊢ (a.2.1 ∈ t ∧ a.2.2 ∈ t) ∧ a.1.1 * a.2.1 = a.1.2 * a.2.2 ↔
    ∃ a_1 a_2 b, (a_2 ∈ t ∧ b ∈ t) ∧ ((a_1 * b, a_1 * a_2), a_2, b) = a

Next tactic:
refine' ⟨fun h => ⟨a.1.1 * a.2.2⁻¹, _, _, h.1, by simp [mul_right_comm, h.2]⟩, _⟩
@[to_additive (attr := simp) additiveEnergy_univ_left]
theorem multiplicativeEnergy_univ_left :
    multiplicativeEnergy univ t = Fintype.card α * t.card ^ 2 := by
  simp only [multiplicativeEnergy, univ_product_univ, Fintype.card, sq, ← card_product]
  let f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
  have : (↑((univ : Finset α) ×ˢ t ×ˢ t) : Set (α × α × α)).InjOn f := by
    rintro ⟨a₁, b₁, c₁⟩ _ ⟨a₂, b₂, c₂⟩ h₂ h
    simp_rw [Prod.ext_iff] at h
    obtain ⟨h, rfl, rfl⟩ := h
    rw [mul_right_cancel h.1]
  rw [← card_image_of_injOn this]
  congr with a
  simp only [mem_filter, mem_product, mem_univ, true_and_iff, mem_image, exists_prop,
    Prod.exists]
  refine' ⟨fun h => ⟨a.1.1 * a.2.2⁻¹, _, _, h.1, by 

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
a : (α × α) × α × α
h : (a.2.1 ∈ t ∧ a.2.2 ∈ t) ∧ a.1.1 * a.2.1 = a.1.2 * a.2.2
⊢ ((a.1.1 * a.2.2⁻¹ * a.2.2, a.1.1 * a.2.2⁻¹ * a.2.1), a.2.1, a.2.2) = a

Next tactic:
simp [mul_right_comm, h.2]
@[to_additive (attr := simp) additiveEnergy_univ_left]
theorem multiplicativeEnergy_univ_left :
    multiplicativeEnergy univ t = Fintype.card α * t.card ^ 2 := by
  simp only [multiplicativeEnergy, univ_product_univ, Fintype.card, sq, ← card_product]
  let f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
  have : (↑((univ : Finset α) ×ˢ t ×ˢ t) : Set (α × α × α)).InjOn f := by
    rintro ⟨a₁, b₁, c₁⟩ _ ⟨a₂, b₂, c₂⟩ h₂ h
    simp_rw [Prod.ext_iff] at h
    obtain ⟨h, rfl, rfl⟩ := h
    rw [mul_right_cancel h.1]
  rw [← card_image_of_injOn this]
  congr with a
  simp only [mem_filter, mem_product, mem_univ, true_and_iff, mem_image, exists_prop,
    Prod.exists]
  refine' ⟨fun h => ⟨a.1.1 * a.2.2⁻¹, _, _, h.1, by simp [mul_right_comm, h.2]⟩, _⟩
  

Proof state:
case e_s.a
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
a : (α × α) × α × α
⊢ (∃ a_1 a_2 b, (a_2 ∈ t ∧ b ∈ t) ∧ ((a_1 * b, a_1 * a_2), a_2, b) = a) →
    (a.2.1 ∈ t ∧ a.2.2 ∈ t) ∧ a.1.1 * a.2.1 = a.1.2 * a.2.2

Next tactic:
rintro ⟨b, c, d, hcd, rfl⟩
@[to_additive (attr := simp) additiveEnergy_univ_left]
theorem multiplicativeEnergy_univ_left :
    multiplicativeEnergy univ t = Fintype.card α * t.card ^ 2 := by
  simp only [multiplicativeEnergy, univ_product_univ, Fintype.card, sq, ← card_product]
  let f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
  have : (↑((univ : Finset α) ×ˢ t ×ˢ t) : Set (α × α × α)).InjOn f := by
    rintro ⟨a₁, b₁, c₁⟩ _ ⟨a₂, b₂, c₂⟩ h₂ h
    simp_rw [Prod.ext_iff] at h
    obtain ⟨h, rfl, rfl⟩ := h
    rw [mul_right_cancel h.1]
  rw [← card_image_of_injOn this]
  congr with a
  simp only [mem_filter, mem_product, mem_univ, true_and_iff, mem_image, exists_prop,
    Prod.exists]
  refine' ⟨fun h => ⟨a.1.1 * a.2.2⁻¹, _, _, h.1, by simp [mul_right_comm, h.2]⟩, _⟩
  rintro ⟨b, c, d, hcd, rfl⟩
  

Proof state:
case e_s.a.intro.intro.intro.intro
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
b c d : α
hcd : c ∈ t ∧ d ∈ t
⊢ (((b * d, b * c), c, d).2.1 ∈ t ∧ ((b * d, b * c), c, d).2.2 ∈ t) ∧
    ((b * d, b * c), c, d).1.1 * ((b * d, b * c), c, d).2.1 = ((b * d, b * c), c, d).1.2 * ((b * d, b * c), c, d).2.2

Next tactic:
simpa [mul_right_comm]
@[to_additive (attr := simp) additiveEnergy_univ_right]
theorem multiplicativeEnergy_univ_right :
    multiplicativeEnergy s univ = Fintype.card α * s.card ^ 2 := by
  

Proof state:
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
⊢ multiplicativeEnergy s univ = Fintype.card α * card s ^ 2

Next tactic:
rw [multiplicativeEnergy_comm, multiplicativeEnergy_univ_left]
theorem conj_eq : q = p / (p - 1) := by
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ q = p / (p - 1)

Next tactic:
have := h.inv_add_inv_conj
theorem conj_eq : q = p / (p - 1) := by
  have := h.inv_add_inv_conj
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
this : 1 / p + 1 / q = 1
⊢ q = p / (p - 1)

Next tactic:
rw [← eq_sub_iff_add_eq', one_div, inv_eq_iff_eq_inv] at this
theorem conj_eq : q = p / (p - 1) := by
  have := h.inv_add_inv_conj
  rw [← eq_sub_iff_add_eq', one_div, inv_eq_iff_eq_inv] at this
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
this : q = (1 - 1 / p)⁻¹
⊢ q = p / (p - 1)

Next tactic:
field_simp [this, h.ne_zero]
theorem mul_eq_add : p * q = p + q := by
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ p * q = p + q

Next tactic:
simpa only [sub_mul, sub_eq_iff_eq_add, one_mul] using h.sub_one_mul_conj
@[symm]
protected theorem symm : q.IsConjugateExponent p :=
  { one_lt := by
      

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ 1 < q

Next tactic:
rw [h.conj_eq]
@[symm]
protected theorem symm : q.IsConjugateExponent p :=
  { one_lt := by
      rw [h.conj_eq]
      

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ 1 < p / (p - 1)

Next tactic:
exact (one_lt_div h.sub_one_pos).mpr (sub_one_lt p)
@[symm]
protected theorem symm : q.IsConjugateExponent p :=
  { one_lt := by
      rw [h.conj_eq]
      exact (one_lt_div h.sub_one_pos).mpr (sub_one_lt p)
    inv_add_inv_conj := by 

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ 1 / q + 1 / p = 1

Next tactic:
simpa [add_comm] using h.inv_add_inv_conj
theorem div_conj_eq_sub_one : p / q = p - 1 := by
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ p / q = p - 1

Next tactic:
field_simp [h.symm.ne_zero]
theorem div_conj_eq_sub_one : p / q = p - 1 := by
  field_simp [h.symm.ne_zero]
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ p = (p - 1) * q

Next tactic:
rw [h.sub_one_mul_conj]
theorem one_lt_nnreal : 1 < Real.toNNReal p := by
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ 1 < toNNReal p

Next tactic:
rw [← Real.toNNReal_one, Real.toNNReal_lt_toNNReal_iff h.pos]
theorem one_lt_nnreal : 1 < Real.toNNReal p := by
  rw [← Real.toNNReal_one, Real.toNNReal_lt_toNNReal_iff h.pos]
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ 1 < p

Next tactic:
exact h.one_lt
theorem inv_add_inv_conj_nnreal : 1 / Real.toNNReal p + 1 / Real.toNNReal q = 1 := by
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ 1 / toNNReal p + 1 / toNNReal q = 1

Next tactic:
rw [← Real.toNNReal_one, ← Real.toNNReal_div' h.nonneg, ← Real.toNNReal_div' h.symm.nonneg,
      ← Real.toNNReal_add h.one_div_nonneg h.symm.one_div_nonneg, h.inv_add_inv_conj]
theorem inv_add_inv_conj_ennreal : 1 / ENNReal.ofReal p + 1 / ENNReal.ofReal q = 1 := by
  

Proof state:
p q : ℝ
h : IsConjugateExponent p q
⊢ 1 / ENNReal.ofReal p + 1 / ENNReal.ofReal q = 1

Next tactic:
rw [← ENNReal.ofReal_one, ← ENNReal.ofReal_div_of_pos h.pos,
      ← ENNReal.ofReal_div_of_pos h.symm.pos,
      ← ENNReal.ofReal_add h.one_div_nonneg h.symm.one_div_nonneg, h.inv_add_inv_conj]
theorem isConjugateExponent_iff {p q : ℝ} (h : 1 < p) : p.IsConjugateExponent q ↔ q = p / (p - 1) :=
  ⟨fun H => H.conj_eq, fun H => ⟨h, by 

Proof state:
p q : ℝ
h : 1 < p
H : q = p / (p - 1)
⊢ 1 / p + 1 / q = 1

Next tactic:
field_simp [H, ne_of_gt (lt_trans zero_lt_one h)]
theorem isConjugateExponent_one_div {a b : ℝ} (ha : 0 < a) (hb : 0 < b) (hab : a + b = 1) :
    (1 / a).IsConjugateExponent (1 / b) :=
  ⟨by 

Proof state:
a b : ℝ
ha : 0 < a
hb : 0 < b
hab : a + b = 1
⊢ 1 < 1 / a

Next tactic:
rw [lt_div_iff ha, one_mul]
theorem isConjugateExponent_one_div {a b : ℝ} (ha : 0 < a) (hb : 0 < b) (hab : a + b = 1) :
    (1 / a).IsConjugateExponent (1 / b) :=
  ⟨by rw [lt_div_iff ha, one_mul]; 

Proof state:
a b : ℝ
ha : 0 < a
hb : 0 < b
hab : a + b = 1
⊢ a < 1

Next tactic:
linarith
theorem isConjugateExponent_one_div {a b : ℝ} (ha : 0 < a) (hb : 0 < b) (hab : a + b = 1) :
    (1 / a).IsConjugateExponent (1 / b) :=
  ⟨by rw [lt_div_iff ha, one_mul]; linarith,
   by 

Proof state:
a b : ℝ
ha : 0 < a
hb : 0 < b
hab : a + b = 1
⊢ 1 / (1 / a) + 1 / (1 / b) = 1

Next tactic:
simp_rw [one_div_one_div]
theorem isConjugateExponent_one_div {a b : ℝ} (ha : 0 < a) (hb : 0 < b) (hab : a + b = 1) :
    (1 / a).IsConjugateExponent (1 / b) :=
  ⟨by rw [lt_div_iff ha, one_mul]; linarith,
   by simp_rw [one_div_one_div]; 

Proof state:
a b : ℝ
ha : 0 < a
hb : 0 < b
hab : a + b = 1
⊢ a + b = 1

Next tactic:
exact hab
/-- Lift a `OneHom` to `Finset` via `image`. -/
@[to_additive (attr := simps) "Lift a `ZeroHom` to `Finset` via `image`"]
def imageOneHom [DecidableEq β] [One β] [OneHomClass F α β] (f : F) : OneHom (Finset α) (Finset β)
    where
  toFun := Finset.image f
  map_one' := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝³ : One α
s : Finset α
a : α
inst✝² : DecidableEq β
inst✝¹ : One β
inst✝ : OneHomClass F α β
f : F
⊢ image (⇑f) 1 = 1

Next tactic:
rw [image_one, map_one, singleton_one]
@[to_additive (attr := simp)]
theorem preimage_inv : s.preimage Inv.inv (inv_injective.injOn _) = s⁻¹ :=
  coe_injective <| by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝¹ : DecidableEq α
inst✝ : InvolutiveInv α
s : Finset α
⊢ ↑(preimage s Inv.inv (_ : Set.InjOn Inv.inv (Inv.inv ⁻¹' ↑s))) = ↑s⁻¹

Next tactic:
rw [coe_preimage, Set.inv_preimage, coe_inv]
@[to_additive (attr := simp, norm_cast)]
theorem coe_pow (s : Finset α) (n : ℕ) : ↑(s ^ n) = (s : Set α) ^ n := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s✝ t : Finset α
a : α
m n✝ : ℕ
s : Finset α
n : ℕ
⊢ ↑(s ^ n) = ↑s ^ n

Next tactic:
change ↑(npowRec n s) = (s: Set α) ^ n
@[to_additive (attr := simp, norm_cast)]
theorem coe_pow (s : Finset α) (n : ℕ) : ↑(s ^ n) = (s : Set α) ^ n := by
  change ↑(npowRec n s) = (s: Set α) ^ n
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s✝ t : Finset α
a : α
m n✝ : ℕ
s : Finset α
n : ℕ
⊢ ↑(npowRec n s) = ↑s ^ n

Next tactic:
induction' n with n ih
@[to_additive (attr := simp, norm_cast)]
theorem coe_pow (s : Finset α) (n : ℕ) : ↑(s ^ n) = (s : Set α) ^ n := by
  change ↑(npowRec n s) = (s: Set α) ^ n
  induction' n with n ih
  · 

Proof state:
case zero
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s✝ t : Finset α
a : α
m n : ℕ
s : Finset α
⊢ ↑(npowRec Nat.zero s) = ↑s ^ Nat.zero

Next tactic:
rw [npowRec, pow_zero, coe_one]
@[to_additive (attr := simp, norm_cast)]
theorem coe_pow (s : Finset α) (n : ℕ) : ↑(s ^ n) = (s : Set α) ^ n := by
  change ↑(npowRec n s) = (s: Set α) ^ n
  induction' n with n ih
  · rw [npowRec, pow_zero, coe_one]
  · 

Proof state:
case succ
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s✝ t : Finset α
a : α
m n✝ : ℕ
s : Finset α
n : ℕ
ih : ↑(npowRec n s) = ↑s ^ n
⊢ ↑(npowRec (Nat.succ n) s) = ↑s ^ Nat.succ n

Next tactic:
rw [npowRec, pow_succ, coe_mul, ih]
@[to_additive]
theorem pow_mem_pow (ha : a ∈ s) : ∀ n : ℕ, a ^ n ∈ s ^ n
  | 0 => by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n : ℕ
ha : a ∈ s
⊢ a ^ 0 ∈ s ^ 0

Next tactic:
rw [pow_zero]
@[to_additive]
theorem pow_mem_pow (ha : a ∈ s) : ∀ n : ℕ, a ^ n ∈ s ^ n
  | 0 => by
    rw [pow_zero]
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n : ℕ
ha : a ∈ s
⊢ 1 ∈ s ^ 0

Next tactic:
exact one_mem_one
@[to_additive]
theorem pow_mem_pow (ha : a ∈ s) : ∀ n : ℕ, a ^ n ∈ s ^ n
  | 0 => by
    rw [pow_zero]
    exact one_mem_one
  | n + 1 => by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n✝ : ℕ
ha : a ∈ s
n : ℕ
⊢ a ^ (n + 1) ∈ s ^ (n + 1)

Next tactic:
rw [pow_succ]
@[to_additive]
theorem pow_mem_pow (ha : a ∈ s) : ∀ n : ℕ, a ^ n ∈ s ^ n
  | 0 => by
    rw [pow_zero]
    exact one_mem_one
  | n + 1 => by
    rw [pow_succ]
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n✝ : ℕ
ha : a ∈ s
n : ℕ
⊢ a * a ^ n ∈ s ^ (n + 1)

Next tactic:
exact mul_mem_mul ha (pow_mem_pow ha n)
@[to_additive]
theorem pow_subset_pow (hst : s ⊆ t) : ∀ n : ℕ, s ^ n ⊆ t ^ n
  | 0 => by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n : ℕ
hst : s ⊆ t
⊢ s ^ 0 ⊆ t ^ 0

Next tactic:
simp [pow_zero]
@[to_additive]
theorem pow_subset_pow (hst : s ⊆ t) : ∀ n : ℕ, s ^ n ⊆ t ^ n
  | 0 => by
    simp [pow_zero]
  | n + 1 => by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n✝ : ℕ
hst : s ⊆ t
n : ℕ
⊢ s ^ (n + 1) ⊆ t ^ (n + 1)

Next tactic:
rw [pow_succ]
@[to_additive]
theorem pow_subset_pow (hst : s ⊆ t) : ∀ n : ℕ, s ^ n ⊆ t ^ n
  | 0 => by
    simp [pow_zero]
  | n + 1 => by
    rw [pow_succ]
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n✝ : ℕ
hst : s ⊆ t
n : ℕ
⊢ s * s ^ n ⊆ t ^ (n + 1)

Next tactic:
exact mul_subset_mul hst (pow_subset_pow hst n)
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) : m ≤ n → s ^ m ⊆ s ^ n := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n : ℕ
hs : 1 ∈ s
⊢ m ≤ n → s ^ m ⊆ s ^ n

Next tactic:
apply Nat.le_induction
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) : m ≤ n → s ^ m ⊆ s ^ n := by
  apply Nat.le_induction
  · 

Proof state:
case base
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n : ℕ
hs : 1 ∈ s
⊢ s ^ m ⊆ s ^ m

Next tactic:
exact fun _ hn => hn
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) : m ≤ n → s ^ m ⊆ s ^ n := by
  apply Nat.le_induction
  · exact fun _ hn => hn
  · 

Proof state:
case succ
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n : ℕ
hs : 1 ∈ s
⊢ ∀ (n : ℕ), m ≤ n → s ^ m ⊆ s ^ n → s ^ m ⊆ s ^ (n + 1)

Next tactic:
intro n _ hmn
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) : m ≤ n → s ^ m ⊆ s ^ n := by
  apply Nat.le_induction
  · exact fun _ hn => hn
  · intro n _ hmn
    

Proof state:
case succ
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n✝ : ℕ
hs : 1 ∈ s
n : ℕ
hn✝ : m ≤ n
hmn : s ^ m ⊆ s ^ n
⊢ s ^ m ⊆ s ^ (n + 1)

Next tactic:
rw [pow_succ]
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) : m ≤ n → s ^ m ⊆ s ^ n := by
  apply Nat.le_induction
  · exact fun _ hn => hn
  · intro n _ hmn
    rw [pow_succ]
    

Proof state:
case succ
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n✝ : ℕ
hs : 1 ∈ s
n : ℕ
hn✝ : m ≤ n
hmn : s ^ m ⊆ s ^ n
⊢ s ^ m ⊆ s * s ^ n

Next tactic:
exact hmn.trans (subset_mul_right (s ^ n) hs)
@[to_additive]
theorem mem_prod_list_ofFn {a : α} {s : Fin n → Finset α} :
    a ∈ (List.ofFn s).prod ↔ ∃ f : ∀ i : Fin n, s i, (List.ofFn fun i => (f i : α)).prod = a := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s✝ t : Finset α
a✝ : α
m n : ℕ
a : α
s : Fin n → Finset α
⊢ a ∈ List.prod (List.ofFn s) ↔ ∃ f, List.prod (List.ofFn fun i => ↑(f i)) = a

Next tactic:
rw [← mem_coe, coe_list_prod, List.map_ofFn, Set.mem_prod_list_ofFn]
@[to_additive]
theorem mem_prod_list_ofFn {a : α} {s : Fin n → Finset α} :
    a ∈ (List.ofFn s).prod ↔ ∃ f : ∀ i : Fin n, s i, (List.ofFn fun i => (f i : α)).prod = a := by
  rw [← mem_coe, coe_list_prod, List.map_ofFn, Set.mem_prod_list_ofFn]
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s✝ t : Finset α
a✝ : α
m n : ℕ
a : α
s : Fin n → Finset α
⊢ (∃ f, List.prod (List.ofFn fun i => ↑(f i)) = a) ↔ ∃ f, List.prod (List.ofFn fun i => ↑(f i)) = a

Next tactic:
rfl
@[to_additive]
theorem mem_pow {a : α} {n : ℕ} :
    a ∈ s ^ n ↔ ∃ f : Fin n → s, (List.ofFn fun i => ↑(f i)).prod = a := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a✝ : α
m n✝ : ℕ
a : α
n : ℕ
⊢ a ∈ s ^ n ↔ ∃ f, List.prod (List.ofFn fun i => ↑(f i)) = a

Next tactic:
simp [← mem_coe, coe_pow, Set.mem_pow]
@[to_additive (attr := simp)]
theorem empty_pow (hn : n ≠ 0) : (∅ : Finset α) ^ n = ∅ := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : Monoid α
s t : Finset α
a : α
m n : ℕ
hn : n ≠ 0
⊢ ∅ ^ n = ∅

Next tactic:
rw [← tsub_add_cancel_of_le (Nat.succ_le_of_lt <| Nat.pos_of_ne_zero hn), pow_succ, empty_mul]
@[to_additive (attr := simp) nsmul_univ]
theorem univ_pow [Fintype α] (hn : n ≠ 0) : (univ : Finset α) ^ n = univ :=
  coe_injective <| by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝³ : DecidableEq α
inst✝² : DecidableEq β
inst✝¹ : Monoid α
s t : Finset α
a : α
m n : ℕ
inst✝ : Fintype α
hn : n ≠ 0
⊢ ↑(univ ^ n) = ↑univ

Next tactic:
rw [coe_pow, coe_univ, Set.univ_pow hn]
@[to_additive (attr := simp)]
theorem coe_zpow (s : Finset α) : ∀ n : ℤ, ↑(s ^ n) = (s : Set α) ^ n
  | Int.ofNat n => coe_pow _ _
  | Int.negSucc n => by
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : DivisionMonoid α
s✝ t s : Finset α
n : ℕ
⊢ ↑(s ^ Int.negSucc n) = ↑s ^ Int.negSucc n

Next tactic:
refine' (coe_inv _).trans _
@[to_additive (attr := simp)]
theorem coe_zpow (s : Finset α) : ∀ n : ℤ, ↑(s ^ n) = (s : Set α) ^ n
  | Int.ofNat n => coe_pow _ _
  | Int.negSucc n => by
    refine' (coe_inv _).trans _
    

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : DivisionMonoid α
s✝ t s : Finset α
n : ℕ
⊢ (↑(npowRec (Nat.succ n) s))⁻¹ = ↑s ^ Int.negSucc n

Next tactic:
exact congr_arg Inv.inv (coe_pow _ _)
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : DivisionMonoid α
s t : Finset α
⊢ s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1

Next tactic:
simp_rw [← coe_inj, coe_mul, coe_one, Set.mul_eq_one_iff, coe_singleton]
@[to_additive (attr := simp)]
theorem isUnit_iff : IsUnit s ↔ ∃ a, s = {a} ∧ IsUnit a := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : DivisionMonoid α
s t : Finset α
⊢ IsUnit s ↔ ∃ a, s = {a} ∧ IsUnit a

Next tactic:
constructor
@[to_additive (attr := simp)]
theorem isUnit_iff : IsUnit s ↔ ∃ a, s = {a} ∧ IsUnit a := by
  constructor
  · 

Proof state:
case mp
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : DivisionMonoid α
s t : Finset α
⊢ IsUnit s → ∃ a, s = {a} ∧ IsUnit a

Next tactic:
rintro ⟨u, rfl⟩
@[to_additive (attr := simp)]
theorem isUnit_iff : IsUnit s ↔ ∃ a, s = {a} ∧ IsUnit a := by
  constructor
  · rintro ⟨u, rfl⟩
    

Proof state:
case mp.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : DivisionMonoid α
t : Finset α
u : (Finset α)ˣ
⊢ ∃ a, ↑u = {a} ∧ IsUnit a

Next tactic:
obtain ⟨a, b, ha, hb, h⟩ := Finset.mul_eq_one_iff.1 u.mul_inv
@[to_additive (attr := simp)]
theorem isUnit_iff : IsUnit s ↔ ∃ a, s = {a} ∧ IsUnit a := by
  constructor
  · rintro ⟨u, rfl⟩
    obtain ⟨a, b, ha, hb, h⟩ := Finset.mul_eq_one_iff.1 u.mul_inv
    

Proof state:
case mp.intro.intro.intro.intro.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝² : DecidableEq α
inst✝¹ : DecidableEq β
inst✝ : DivisionMonoid α
t : Finset α
u : (Finset α)ˣ
a b : α
ha : ↑u = {a}
hb : ↑u⁻¹ = {b}
h : a * b = 1
⊢ ∃ a, ↑u = {a} ∧ IsUnit a

Next tactic:
refine' ⟨a, ha, ⟨a, b, h, singleton_injective _⟩, rfl⟩