l3lab/ntp-mathlib huggingface dataset:
/-- The bijection between a `CommGroup` and its `ConjClasses`. -/
def mkEquiv : α ≃ ConjClasses α :=
  ⟨ConjClasses.mk, Quotient.lift id fun (a : α) b => isConj_iff_eq.1, Quotient.lift_mk _ _, by
    rw [Function.RightInverse, Function.LeftInverse, forall_isConj]
    intro x
    

Proof state:
α : Type u
β : Type v
inst✝ : CommMonoid α
x : α
⊢ ConjClasses.mk (Quotient.lift id (_ : ∀ (a b : α), IsConj a b → a = b) (ConjClasses.mk x)) = ConjClasses.mk x

Next tactic:
rw [← quotient_mk_eq_mk, ← quotient_mk_eq_mk, Quotient.lift_mk, id.def]
theorem isConj_iff_conjugatesOf_eq {a b : α} : IsConj a b ↔ conjugatesOf a = conjugatesOf b :=
  ⟨IsConj.conjugatesOf_eq, fun h => by
    

Proof state:
α : Type u
β : Type v
inst✝ : Monoid α
a b : α
h : conjugatesOf a = conjugatesOf b
⊢ IsConj a b

Next tactic:
have ha := @mem_conjugatesOf_self _ _ b
theorem isConj_iff_conjugatesOf_eq {a b : α} : IsConj a b ↔ conjugatesOf a = conjugatesOf b :=
  ⟨IsConj.conjugatesOf_eq, fun h => by
    have ha := @mem_conjugatesOf_self _ _ b -- Porting note: added `@`.
    

Proof state:
α : Type u
β : Type v
inst✝ : Monoid α
a b : α
h : conjugatesOf a = conjugatesOf b
ha : b ∈ conjugatesOf b
⊢ IsConj a b

Next tactic:
rwa [← h] at ha
theorem mem_carrier_iff_mk_eq {a : α} {b : ConjClasses α} :
    a ∈ carrier b ↔ ConjClasses.mk a = b := by
  

Proof state:
α : Type u
β : Type v
inst✝ : Monoid α
a : α
b : ConjClasses α
⊢ a ∈ carrier b ↔ ConjClasses.mk a = b

Next tactic:
revert b
theorem mem_carrier_iff_mk_eq {a : α} {b : ConjClasses α} :
    a ∈ carrier b ↔ ConjClasses.mk a = b := by
  revert b
  

Proof state:
α : Type u
β : Type v
inst✝ : Monoid α
a : α
⊢ ∀ {b : ConjClasses α}, a ∈ carrier b ↔ ConjClasses.mk a = b

Next tactic:
rw [forall_isConj]
theorem mem_carrier_iff_mk_eq {a : α} {b : ConjClasses α} :
    a ∈ carrier b ↔ ConjClasses.mk a = b := by
  revert b
  rw [forall_isConj]
  

Proof state:
α : Type u
β : Type v
inst✝ : Monoid α
a : α
⊢ ∀ (a_1 : α), a ∈ carrier (ConjClasses.mk a_1) ↔ ConjClasses.mk a = ConjClasses.mk a_1

Next tactic:
intro b
theorem mem_carrier_iff_mk_eq {a : α} {b : ConjClasses α} :
    a ∈ carrier b ↔ ConjClasses.mk a = b := by
  revert b
  rw [forall_isConj]
  intro b
  

Proof state:
α : Type u
β : Type v
inst✝ : Monoid α
a b : α
⊢ a ∈ carrier (ConjClasses.mk b) ↔ ConjClasses.mk a = ConjClasses.mk b

Next tactic:
rw [carrier, eq_comm, mk_eq_mk_iff_isConj, ← quotient_mk_eq_mk, Quotient.lift_mk]
theorem mem_carrier_iff_mk_eq {a : α} {b : ConjClasses α} :
    a ∈ carrier b ↔ ConjClasses.mk a = b := by
  revert b
  rw [forall_isConj]
  intro b
  rw [carrier, eq_comm, mk_eq_mk_iff_isConj, ← quotient_mk_eq_mk, Quotient.lift_mk]
  

Proof state:
α : Type u
β : Type v
inst✝ : Monoid α
a b : α
⊢ a ∈ conjugatesOf b ↔ IsConj b a

Next tactic:
rfl
@[simp]
theorem lift_continuum : lift.{v} 𝔠 = 𝔠 := by
  

Proof state:
⊢ lift.{v, u_1} 𝔠 = 𝔠

Next tactic:
rw [← two_power_aleph0, lift_two_power, lift_aleph0, two_power_aleph0]
@[simp]
theorem continuum_le_lift {c : Cardinal.{u}} : 𝔠 ≤ lift.{v} c ↔ 𝔠 ≤ c := by
  -- porting note: added explicit universes
  

Proof state:
c : Cardinal.{u}
⊢ 𝔠 ≤ lift.{v, u} c ↔ 𝔠 ≤ c

Next tactic:
rw [← lift_continuum.{u,v}, lift_le]
@[simp]
theorem lift_le_continuum {c : Cardinal.{u}} : lift.{v} c ≤ 𝔠 ↔ c ≤ 𝔠 := by
  -- porting note: added explicit universes
  

Proof state:
c : Cardinal.{u}
⊢ lift.{v, u} c ≤ 𝔠 ↔ c ≤ 𝔠

Next tactic:
rw [← lift_continuum.{u,v}, lift_le]
@[simp]
theorem continuum_lt_lift {c : Cardinal.{u}} : 𝔠 < lift.{v} c ↔ 𝔠 < c := by
  -- porting note: added explicit universes
  

Proof state:
c : Cardinal.{u}
⊢ 𝔠 < lift.{v, u} c ↔ 𝔠 < c

Next tactic:
rw [← lift_continuum.{u,v}, lift_lt]
@[simp]
theorem lift_lt_continuum {c : Cardinal.{u}} : lift.{v} c < 𝔠 ↔ c < 𝔠 := by
  -- porting note: added explicit universes
  

Proof state:
c : Cardinal.{u}
⊢ lift.{v, u} c < 𝔠 ↔ c < 𝔠

Next tactic:
rw [← lift_continuum.{u,v}, lift_lt]
@[simp]
theorem beth_one : beth 1 = 𝔠 := by 

Proof state:
⊢ beth 1 = 𝔠

Next tactic:
simpa using beth_succ 0
theorem mk_set_nat : #(Set ℕ) = 𝔠 := by 

Proof state:
⊢ #(Set ℕ) = 𝔠

Next tactic:
simp
theorem aleph_one_le_continuum : aleph 1 ≤ 𝔠 := by
  

Proof state:
⊢ aleph 1 ≤ 𝔠

Next tactic:
rw [← succ_aleph0]
theorem aleph_one_le_continuum : aleph 1 ≤ 𝔠 := by
  rw [← succ_aleph0]
  

Proof state:
⊢ Order.succ ℵ₀ ≤ 𝔠

Next tactic:
exact Order.succ_le_of_lt aleph0_lt_continuum
@[simp]
theorem continuum_power_aleph0 : continuum.{u} ^ aleph0.{u} = 𝔠 := by
  

Proof state:
⊢ 𝔠 ^ ℵ₀ = 𝔠

Next tactic:
rw [← two_power_aleph0, ← power_mul, mul_eq_left le_rfl le_rfl aleph0_ne_zero]
@[to_additive]
theorem inv_mem_inv : a⁻¹ ∈ s⁻¹ ↔ a ∈ s := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s t : Set α
a : α
⊢ a⁻¹ ∈ s⁻¹ ↔ a ∈ s

Next tactic:
simp only [mem_inv, inv_inv]
@[to_additive (attr := simp)]
noncomputable instance involutiveInv : InvolutiveInv (Set α) where
  inv := Inv.inv
  inv_inv s := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s✝ t : Set α
a : α
s : Set α
⊢ s⁻¹⁻¹ = s

Next tactic:
simp only [← inv_preimage, preimage_preimage, inv_inv, preimage_id']
@[to_additive]
theorem inv_subset : s⁻¹ ⊆ t ↔ s ⊆ t⁻¹ := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s t : Set α
a : α
⊢ s⁻¹ ⊆ t ↔ s ⊆ t⁻¹

Next tactic:
rw [← inv_subset_inv, inv_inv]
@[to_additive (attr := simp)]
theorem inv_singleton (a : α) : ({a} : Set α)⁻¹ = {a⁻¹} := by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s t : Set α
a✝ a : α
⊢ {a}⁻¹ = {a⁻¹}

Next tactic:
rw [← image_inv, image_singleton]
@[to_additive (attr := simp)]
theorem inv_insert (a : α) (s : Set α) : (insert a s)⁻¹ = insert a⁻¹ s⁻¹ := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s✝ t : Set α
a✝ a : α
s : Set α
⊢ (insert a s)⁻¹ = insert a⁻¹ s⁻¹

Next tactic:
rw [insert_eq, union_inv, inv_singleton, insert_eq]
@[to_additive]
theorem inv_range {ι : Sort*} {f : ι → α} : (range f)⁻¹ = range fun i => (f i)⁻¹ := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s t : Set α
a : α
ι : Sort u_5
f : ι → α
⊢ (range f)⁻¹ = range fun i => (f i)⁻¹

Next tactic:
rw [← image_inv]
@[to_additive]
theorem inv_range {ι : Sort*} {f : ι → α} : (range f)⁻¹ = range fun i => (f i)⁻¹ := by
  rw [← image_inv]
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s t : Set α
a : α
ι : Sort u_5
f : ι → α
⊢ Inv.inv '' range f = range fun i => (f i)⁻¹

Next tactic:
exact (range_comp _ _).symm
@[to_additive]
theorem image_op_inv : op '' s⁻¹ = (op '' s)⁻¹ := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : InvolutiveInv α
s t : Set α
a : α
⊢ op '' s⁻¹ = (op '' s)⁻¹

Next tactic:
simp_rw [← image_inv, Function.Semiconj.set_image op_inv s]
@[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✝ : Monoid α
s t : Set α
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✝ : Monoid α
s t : Set α
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✝ : Monoid α
s t : Set α
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✝ : Monoid α
s t : Set α
a : α
m n✝ : ℕ
ha : a ∈ s
n : ℕ
⊢ a * a ^ n ∈ s ^ (n + 1)

Next tactic:
exact mul_mem_mul ha (pow_mem_pow ha _)
@[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✝ : Monoid α
s t : Set α
a : α
m n : ℕ
hst : s ⊆ t
⊢ s ^ 0 ⊆ t ^ 0

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

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

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

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : Monoid α
s t : Set α
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
    rw [pow_zero]
    exact Subset.rfl
  | n + 1 => by
    rw [pow_succ]
    

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

Next tactic:
exact mul_subset_mul hst (pow_subset_pow hst _)
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) (hn : m ≤ n) : s ^ m ⊆ s ^ n := by
  -- Porting note: `Nat.le_induction` didn't work as an induction principle in mathlib3, this was
  -- `refine Nat.le_induction ...`
  

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

Next tactic:
induction' n, hn using Nat.le_induction with _ _ ih
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) (hn : m ≤ n) : s ^ m ⊆ s ^ n := by
  -- Porting note: `Nat.le_induction` didn't work as an induction principle in mathlib3, this was
  -- `refine Nat.le_induction ...`
  induction' n, hn using Nat.le_induction with _ _ ih
  · 

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

Next tactic:
exact Subset.rfl
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) (hn : m ≤ n) : s ^ m ⊆ s ^ n := by
  -- Porting note: `Nat.le_induction` didn't work as an induction principle in mathlib3, this was
  -- `refine Nat.le_induction ...`
  induction' n, hn using Nat.le_induction with _ _ ih
  · exact Subset.rfl
  · 

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

Next tactic:
dsimp only
@[to_additive]
theorem pow_subset_pow_of_one_mem (hs : (1 : α) ∈ s) (hn : m ≤ n) : s ^ m ⊆ s ^ n := by
  -- Porting note: `Nat.le_induction` didn't work as an induction principle in mathlib3, this was
  -- `refine Nat.le_induction ...`
  induction' n, hn using Nat.le_induction with _ _ ih
  · exact Subset.rfl
  · dsimp only
    

Proof state:
case succ
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : Monoid α
s t : Set α
a : α
m n : ℕ
hs : 1 ∈ s
n✝ : ℕ
hn✝ : m ≤ n✝
ih : 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) (hn : m ≤ n) : s ^ m ⊆ s ^ n := by
  -- Porting note: `Nat.le_induction` didn't work as an induction principle in mathlib3, this was
  -- `refine Nat.le_induction ...`
  induction' n, hn using Nat.le_induction with _ _ ih
  · exact Subset.rfl
  · dsimp only
    rw [pow_succ]
    

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

Next tactic:
exact ih.trans (subset_mul_right _ hs)
@[to_additive (attr := simp)]
theorem empty_pow {n : ℕ} (hn : n ≠ 0) : (∅ : Set α) ^ n = ∅ := by
  

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : Monoid α
s t : Set α
a : α
m n✝ 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]
@[simp]
theorem nsmul_univ {α : Type*} [AddMonoid α] : ∀ {n : ℕ}, n ≠ 0 → n • (univ : Set α) = univ
  | 0 => fun h => (h rfl).elim
  | 1 => fun _ => one_nsmul _
  | n + 2 => fun _ => by 

Proof state:
F : Type u_1
α✝ : Type u_2
β : Type u_3
γ : Type u_4
inst✝¹ : Monoid α✝
s t : Set α✝
a : α✝
m n✝ : ℕ
α : Type u_5
inst✝ : AddMonoid α
n : ℕ
x✝ : n + 2 ≠ 0
⊢ (n + 2) • univ = univ

Next tactic:
rw [succ_nsmul, nsmul_univ n.succ_ne_zero, univ_add_univ]
@[to_additive existing (attr := simp) nsmul_univ]
theorem univ_pow : ∀ {n : ℕ}, n ≠ 0 → (univ : Set α) ^ n = univ
  | 0 => fun h => (h rfl).elim
  | 1 => fun _ => pow_one _
  | n + 2 => fun _ => by 

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : Monoid α
s t : Set α
a : α
m n✝ n : ℕ
x✝ : n + 2 ≠ 0
⊢ univ ^ (n + 2) = univ

Next tactic:
rw [pow_succ, univ_pow n.succ_ne_zero, univ_mul_univ]
@[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✝ : DivisionMonoid α
s t : Set α
⊢ s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1

Next tactic:
refine' ⟨fun h => _, _⟩
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · 

Proof state:
case refine'_1
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
⊢ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1

Next tactic:
have hst : (s * t).Nonempty := h.symm.subst one_nonempty
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    

Proof state:
case refine'_1
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
⊢ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1

Next tactic:
obtain ⟨a, ha⟩ := hst.of_image2_left
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    

Proof state:
case refine'_1.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
a : α
ha : a ∈ s
⊢ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1

Next tactic:
obtain ⟨b, hb⟩ := hst.of_image2_right
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    

Proof state:
case refine'_1.intro.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
a : α
ha : a ∈ s
b : α
hb : b ∈ t
⊢ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1

Next tactic:
have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
    

Proof state:
case refine'_1.intro.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
a : α
ha : a ∈ s
b : α
hb : b ∈ t
H : ∀ {a b : α}, a ∈ s → b ∈ t → a * b = 1
⊢ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1

Next tactic:
refine' ⟨a, b, _, _, H ha hb⟩
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
    refine' ⟨a, b, _, _, H ha hb⟩ <;> 

Proof state:
case refine'_1.intro.intro.refine'_1
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
a : α
ha : a ∈ s
b : α
hb : b ∈ t
H : ∀ {a b : α}, a ∈ s → b ∈ t → a * b = 1
⊢ s = {a}

Next tactic:
refine' eq_singleton_iff_unique_mem.2 ⟨‹_›, fun x hx => _⟩
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
    refine' ⟨a, b, _, _, H ha hb⟩ <;> 

Proof state:
case refine'_1.intro.intro.refine'_2
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
a : α
ha : a ∈ s
b : α
hb : b ∈ t
H : ∀ {a b : α}, a ∈ s → b ∈ t → a * b = 1
⊢ t = {b}

Next tactic:
refine' eq_singleton_iff_unique_mem.2 ⟨‹_›, fun x hx => _⟩
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
    refine' ⟨a, b, _, _, H ha hb⟩ <;> refine' eq_singleton_iff_unique_mem.2 ⟨‹_›, fun x hx => _⟩
    · 

Proof state:
case refine'_1.intro.intro.refine'_1
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
a : α
ha : a ∈ s
b : α
hb : b ∈ t
H : ∀ {a b : α}, a ∈ s → b ∈ t → a * b = 1
x : α
hx : x ∈ s
⊢ x = a

Next tactic:
exact (eq_inv_of_mul_eq_one_left <| H hx hb).trans (inv_eq_of_mul_eq_one_left <| H ha hb)
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
    refine' ⟨a, b, _, _, H ha hb⟩ <;> refine' eq_singleton_iff_unique_mem.2 ⟨‹_›, fun x hx => _⟩
    · exact (eq_inv_of_mul_eq_one_left <| H hx hb).trans (inv_eq_of_mul_eq_one_left <| H ha hb)
    · 

Proof state:
case refine'_1.intro.intro.refine'_2
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
h : s * t = 1
hst : Set.Nonempty (s * t)
a : α
ha : a ∈ s
b : α
hb : b ∈ t
H : ∀ {a b : α}, a ∈ s → b ∈ t → a * b = 1
x : α
hx : x ∈ t
⊢ x = b

Next tactic:
exact (eq_inv_of_mul_eq_one_right <| H ha hx).trans (inv_eq_of_mul_eq_one_right <| H ha hb)
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
    refine' ⟨a, b, _, _, H ha hb⟩ <;> refine' eq_singleton_iff_unique_mem.2 ⟨‹_›, fun x hx => _⟩
    · exact (eq_inv_of_mul_eq_one_left <| H hx hb).trans (inv_eq_of_mul_eq_one_left <| H ha hb)
    · exact (eq_inv_of_mul_eq_one_right <| H ha hx).trans (inv_eq_of_mul_eq_one_right <| H ha hb)
  · 

Proof state:
case refine'_2
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s t : Set α
⊢ (∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1) → s * t = 1

Next tactic:
rintro ⟨b, c, rfl, rfl, h⟩
@[to_additive]
protected theorem mul_eq_one_iff : s * t = 1 ↔ ∃ a b, s = {a} ∧ t = {b} ∧ a * b = 1 := by
  refine' ⟨fun h => _, _⟩
  · have hst : (s * t).Nonempty := h.symm.subst one_nonempty
    obtain ⟨a, ha⟩ := hst.of_image2_left
    obtain ⟨b, hb⟩ := hst.of_image2_right
    have H : ∀ {a b}, a ∈ s → b ∈ t → a * b = (1 : α) := fun {a b} ha hb =>
      h.subset <| mem_image2_of_mem ha hb
    refine' ⟨a, b, _, _, H ha hb⟩ <;> refine' eq_singleton_iff_unique_mem.2 ⟨‹_›, fun x hx => _⟩
    · exact (eq_inv_of_mul_eq_one_left <| H hx hb).trans (inv_eq_of_mul_eq_one_left <| H ha hb)
    · exact (eq_inv_of_mul_eq_one_right <| H ha hx).trans (inv_eq_of_mul_eq_one_right <| H ha hb)
  · rintro ⟨b, c, rfl, rfl, h⟩
    

Proof state:
case refine'_2.intro.intro.intro.intro
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
b c : α
h : b * c = 1
⊢ {b} * {c} = 1

Next tactic:
rw [singleton_mul_singleton, h, singleton_one]
/-- `Set α` is a division monoid under pointwise operations if `α` is. -/
@[to_additive subtractionMonoid
    "`Set α` is a subtraction monoid under pointwise operations if `α` is."]
protected noncomputable def divisionMonoid : DivisionMonoid (Set α) :=
  { Set.monoid, Set.involutiveInv, Set.div, @Set.ZPow α _ _ _ with
    mul_inv_rev := fun s t => by
      simp_rw [← image_inv]
      exact image_image2_antidistrib mul_inv_rev
    inv_eq_of_mul := fun s t h => by
      obtain ⟨a, b, rfl, rfl, hab⟩ := Set.mul_eq_one_iff.1 h
      rw [inv_singleton, inv_eq_of_mul_eq_one_right hab]
    div_eq_mul_inv := fun s t => by
      

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s✝ t✝ : Set α
src✝³ : Monoid (Set α) := Set.monoid
src✝² : InvolutiveInv (Set α) := involutiveInv
src✝¹ : Div (Set α) := Set.div
src✝ : Pow (Set α) ℤ := Set.ZPow
s t : Set α
⊢ s / t = s * t⁻¹

Next tactic:
rw [← image_id (s / t), ← image_inv]
/-- `Set α` is a division monoid under pointwise operations if `α` is. -/
@[to_additive subtractionMonoid
    "`Set α` is a subtraction monoid under pointwise operations if `α` is."]
protected noncomputable def divisionMonoid : DivisionMonoid (Set α) :=
  { Set.monoid, Set.involutiveInv, Set.div, @Set.ZPow α _ _ _ with
    mul_inv_rev := fun s t => by
      simp_rw [← image_inv]
      exact image_image2_antidistrib mul_inv_rev
    inv_eq_of_mul := fun s t h => by
      obtain ⟨a, b, rfl, rfl, hab⟩ := Set.mul_eq_one_iff.1 h
      rw [inv_singleton, inv_eq_of_mul_eq_one_right hab]
    div_eq_mul_inv := fun s t => by
      rw [← image_id (s / t), ← image_inv]
      

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s✝ t✝ : Set α
src✝³ : Monoid (Set α) := Set.monoid
src✝² : InvolutiveInv (Set α) := involutiveInv
src✝¹ : Div (Set α) := Set.div
src✝ : Pow (Set α) ℤ := Set.ZPow
s t : Set α
⊢ id '' (s / t) = s * Inv.inv '' t

Next tactic:
exact image_image2_distrib_right div_eq_mul_inv
/-- `Set α` is a division monoid under pointwise operations if `α` is. -/
@[to_additive subtractionMonoid
    "`Set α` is a subtraction monoid under pointwise operations if `α` is."]
protected noncomputable def divisionMonoid : DivisionMonoid (Set α) :=
  { Set.monoid, Set.involutiveInv, Set.div, @Set.ZPow α _ _ _ with
    mul_inv_rev := fun s t => by
      

Proof state:
F : Type u_1
α : Type u_2
β : Type u_3
γ : Type u_4
inst✝ : DivisionMonoid α
s✝ t✝ : Set α
src✝³ : Monoid (Set α) := Set.monoid
src✝² : InvolutiveInv (Set α) := involutiveInv
src✝¹ : Div (Set α) := Set.div
src✝ : Pow (Set α) ℤ := Set.ZPow
s t : Set α
⊢ (s * t)⁻¹ = t⁻¹ * s⁻¹

Next tactic:
simp_rw [← image_inv]