Module docstring
{"# Conjugacy of group elements
See also MulAut.conj and Quandle.conj.
"}
{"# Conjugacy of group elements
See also MulAut.conj and Quandle.conj.
"}
IsConj
      definition
     (a b : α)
        /-- We say that `a` is conjugate to `b` if for some unit `c` we have `c * a * c⁻¹ = b`. -/
def IsConj (a b : α) :=
  ∃ c : αˣ, SemiconjBy (↑c) a b
        IsConj.refl
      theorem
     (a : α) : IsConj a a
        @[refl]
theorem IsConj.refl (a : α) : IsConj a a :=
  ⟨1, SemiconjBy.one_left a⟩
        IsConj.symm
      theorem
     {a b : α} : IsConj a b → IsConj b a
        @[symm]
theorem IsConj.symm {a b : α} : IsConj a b → IsConj b a
  | ⟨c, hc⟩ => ⟨c⁻¹, hc.units_inv_symm_left⟩
        isConj_comm
      theorem
     {g h : α} : IsConj g h ↔ IsConj h g
        theorem isConj_comm {g h : α} : IsConjIsConj g h ↔ IsConj h g :=
  ⟨IsConj.symm, IsConj.symm⟩
        IsConj.trans
      theorem
     {a b c : α} : IsConj a b → IsConj b c → IsConj a c
        @[trans]
theorem IsConj.trans {a b c : α} : IsConj a b → IsConj b c → IsConj a c
  | ⟨c₁, hc₁⟩, ⟨c₂, hc₂⟩ => ⟨c₂ * c₁, hc₂.mul_left hc₁⟩
        IsConj.pow
      theorem
     {a b : α} (n : ℕ) : IsConj a b → IsConj (a ^ n) (b ^ n)
        theorem IsConj.pow {a b : α} (n : ℕ) : IsConj a b → IsConj (a^n) (b^n)
  | ⟨c, hc⟩ => ⟨c, hc.pow_right n⟩
        isConj_iff_eq
      theorem
     {α : Type*} [CommMonoid α] {a b : α} : IsConj a b ↔ a = b
        @[simp]
theorem isConj_iff_eq {α : Type*} [CommMonoid α] {a b : α} : IsConjIsConj a b ↔ a = b :=
  ⟨fun ⟨c, hc⟩ => by
    rw [SemiconjBy, mul_comm, ← Units.mul_inv_eq_iff_eq_mul, mul_assoc, c.mul_inv, mul_one] at hc
    exact hc, fun h => by rw [h]⟩
        MonoidHom.map_isConj
      theorem
     (f : α →* β) {a b : α} : IsConj a b → IsConj (f a) (f b)
        protected theorem MonoidHom.map_isConj (f : α →* β) {a b : α} : IsConj a b → IsConj (f a) (f b)
  | ⟨c, hc⟩ => ⟨Units.map f c, by rw [Units.coe_map, SemiconjBy, ← f.map_mul, hc.eq, f.map_mul]⟩
        isConj_one_right
      theorem
     {a : α} : IsConj 1 a ↔ a = 1
        @[simp]
theorem isConj_one_right {a : α} : IsConjIsConj 1 a ↔ a = 1 := by
  refine ⟨fun ⟨c, h⟩ => ?_, fun h => by rw [h]⟩
  rw [SemiconjBy, mul_one] at h
  exact c.isUnit.mul_eq_right.mp h.symm
        isConj_one_left
      theorem
     {a : α} : IsConj a 1 ↔ a = 1
        @[simp]
theorem isConj_one_left {a : α} : IsConjIsConj a 1 ↔ a = 1 :=
  calc
    IsConj a 1 ↔ IsConj 1 a := ⟨IsConj.symm, IsConj.symm⟩
    _ ↔ a = 1 := isConj_one_right
        isConj_iff
      theorem
     {a b : α} : IsConj a b ↔ ∃ c : α, c * a * c⁻¹ = b
        
      conj_inv
      theorem
     {a b : α} : (b * a * b⁻¹)⁻¹ = b * a⁻¹ * b⁻¹
        theorem conj_inv {a b : α} : (b * a * b⁻¹)⁻¹ = b * a⁻¹ * b⁻¹ :=
  (map_inv (MulAut.conj b) a).symm
        conj_mul
      theorem
     {a b c : α} : b * a * b⁻¹ * (b * c * b⁻¹) = b * (a * c) * b⁻¹
        
      conj_pow
      theorem
     {i : ℕ} {a b : α} : (a * b * a⁻¹) ^ i = a * b ^ i * a⁻¹
        
      conj_zpow
      theorem
     {i : ℤ} {a b : α} : (a * b * a⁻¹) ^ i = a * b ^ i * a⁻¹
        @[simp]
theorem conj_zpow {i : ℤ} {a b : α} : (a * b * a⁻¹) ^ i = a * b ^ i * a⁻¹ := by
  cases i
  · simp
  · simp only [zpow_negSucc, conj_pow, mul_inv_rev, inv_inv]
    rw [mul_assoc]
        conj_injective
      theorem
     {x : α} : Function.Injective fun g : α => x * g * x⁻¹
        theorem conj_injective {x : α} : Function.Injective fun g : α => x * g * x⁻¹ :=
  (MulAut.conj x).injective
        IsConj.setoid
      definition
     (α : Type*) [Monoid α] : Setoid α
        /-- The setoid of the relation `IsConj` iff there is a unit `u` such that `u * x = y * u` -/
protected def setoid (α : Type*) [Monoid α] : Setoid α where
  r := IsConj
  iseqv := ⟨IsConj.refl, IsConj.symm, IsConj.trans⟩
        ConjClasses
      definition
     (α : Type*) [Monoid α] : Type _
        /-- The quotient type of conjugacy classes of a group. -/
def ConjClasses (α : Type*) [Monoid α] : Type _ :=
  Quotient (IsConj.setoid α)
        ConjClasses.mk
      definition
     {α : Type*} [Monoid α] (a : α) : ConjClasses α
        /-- The canonical quotient map from a monoid `α` into the `ConjClasses` of `α` -/
protected def mk {α : Type*} [Monoid α] (a : α) : ConjClasses α := ⟦a⟧
        ConjClasses.instInhabited
      instance
     : Inhabited (ConjClasses α)
        instance : Inhabited (ConjClasses α) := ⟨⟦1⟧⟩
        ConjClasses.mk_eq_mk_iff_isConj
      theorem
     {a b : α} : ConjClasses.mk a = ConjClasses.mk b ↔ IsConj a b
        theorem mk_eq_mk_iff_isConj {a b : α} : ConjClasses.mkConjClasses.mk a = ConjClasses.mk b ↔ IsConj a b :=
  Iff.intro Quotient.exact Quot.sound
        ConjClasses.quotient_mk_eq_mk
      theorem
     (a : α) : ⟦a⟧ = ConjClasses.mk a
        theorem quotient_mk_eq_mk (a : α) : ⟦a⟧ = ConjClasses.mk a :=
  rfl
        ConjClasses.quot_mk_eq_mk
      theorem
     (a : α) : Quot.mk Setoid.r a = ConjClasses.mk a
        theorem quot_mk_eq_mk (a : α) : Quot.mk Setoid.r a = ConjClasses.mk a :=
  rfl
        ConjClasses.forall_isConj
      theorem
     {p : ConjClasses α → Prop} : (∀ a, p a) ↔ ∀ a, p (ConjClasses.mk a)
        theorem forall_isConj {p : ConjClasses α → Prop} : (∀ a, p a) ↔ ∀ a, p (ConjClasses.mk a) :=
  Iff.intro (fun h _ => h _) fun h a => Quotient.inductionOn a h
        ConjClasses.mk_surjective
      theorem
     : Function.Surjective (@ConjClasses.mk α _)
        theorem mk_surjective : Function.Surjective (@ConjClasses.mk α _) :=
  forall_isConj.2 fun a => ⟨a, rfl⟩
        ConjClasses.instOne
      instance
     : One (ConjClasses α)
        instance : One (ConjClasses α) :=
  ⟨⟦1⟧⟩
        ConjClasses.one_eq_mk_one
      theorem
     : (1 : ConjClasses α) = ConjClasses.mk 1
        theorem one_eq_mk_one : (1 : ConjClasses α) = ConjClasses.mk 1 :=
  rfl
        ConjClasses.exists_rep
      theorem
     (a : ConjClasses α) : ∃ a0 : α, ConjClasses.mk a0 = a
        theorem exists_rep (a : ConjClasses α) : ∃ a0 : α, ConjClasses.mk a0 = a :=
  Quot.exists_rep a
        ConjClasses.map
      definition
     (f : α →* β) : ConjClasses α → ConjClasses β
        /-- A `MonoidHom` maps conjugacy classes of one group to conjugacy classes of another. -/
def map (f : α →* β) : ConjClasses α → ConjClasses β :=
  Quotient.lift (ConjClasses.mkConjClasses.mk ∘ f) fun _ _ ab => mk_eq_mk_iff_isConj.2 (f.map_isConj ab)
        ConjClasses.map_surjective
      theorem
     {f : α →* β} (hf : Function.Surjective f) : Function.Surjective (ConjClasses.map f)
        theorem map_surjective {f : α →* β} (hf : Function.Surjective f) :
    Function.Surjective (ConjClasses.map f) := by
  intro b
  obtain ⟨b, rfl⟩ := ConjClasses.mk_surjective b
  obtain ⟨a, rfl⟩ := hf b
  exact ⟨ConjClasses.mk a, rfl⟩
        ConjClasses.instDecidableEqOfDecidableRelIsConj
      instance
     [DecidableRel (IsConj : α → α → Prop)] : DecidableEq (ConjClasses α)
        instance (priority := 900) [DecidableRel (IsConj : α → α → Prop)] : DecidableEq (ConjClasses α) :=
  inferInstanceAs <| DecidableEq <| Quotient (IsConj.setoid α)
        ConjClasses.mk_injective
      theorem
     : Function.Injective (@ConjClasses.mk α _)
        theorem mk_injective : Function.Injective (@ConjClasses.mk α _) := fun _ _ =>
  (mk_eq_mk_iff_isConj.trans isConj_iff_eq).1
        ConjClasses.mk_bijective
      theorem
     : Function.Bijective (@ConjClasses.mk α _)
        theorem mk_bijective : Function.Bijective (@ConjClasses.mk α _) :=
  ⟨mk_injective, mk_surjective⟩
        ConjClasses.mkEquiv
      definition
     : α ≃ ConjClasses α
        /-- The bijection between a `CommGroup` and its `ConjClasses`. -/
def mkEquiv : α ≃ ConjClasses α :=
  ⟨ConjClasses.mk, Quotient.lift id fun (_ : α) _ => isConj_iff_eq.1, Quotient.lift_mk _ _, by
    rw [Function.RightInverse, Function.LeftInverse, forall_isConj]
    intro x
    rw [← quotient_mk_eq_mk, ← quotient_mk_eq_mk, Quotient.lift_mk, id]⟩
        conjugatesOf
      definition
     (a : α) : Set α
        /-- Given an element `a`, `conjugatesOf a` is the set of conjugates. -/
def conjugatesOf (a : α) : Set α :=
  { b | IsConj a b }
        mem_conjugatesOf_self
      theorem
     {a : α} : a ∈ conjugatesOf a
        theorem mem_conjugatesOf_self {a : α} : a ∈ conjugatesOf a :=
  IsConj.refl _
        IsConj.conjugatesOf_eq
      theorem
     {a b : α} (ab : IsConj a b) : conjugatesOf a = conjugatesOf b
        theorem IsConj.conjugatesOf_eq {a b : α} (ab : IsConj a b) : conjugatesOf a = conjugatesOf b :=
  Set.ext fun _ => ⟨fun ag => ab.symm.trans ag, fun bg => ab.trans bg⟩
        isConj_iff_conjugatesOf_eq
      theorem
     {a b : α} : IsConj a b ↔ conjugatesOf a = conjugatesOf b
        
      ConjClasses.carrier
      definition
     : ConjClasses α → Set α
        /-- Given a conjugacy class `a`, `carrier a` is the set it represents. -/
def carrier : ConjClasses α → Set α :=
  Quotient.lift conjugatesOf fun (_ : α) _ ab => IsConj.conjugatesOf_eq ab
        ConjClasses.mem_carrier_mk
      theorem
     {a : α} : a ∈ carrier (ConjClasses.mk a)
        theorem mem_carrier_mk {a : α} : a ∈ carrier (ConjClasses.mk a) :=
  IsConj.refl _
        ConjClasses.mem_carrier_iff_mk_eq
      theorem
     {a : α} {b : ConjClasses α} : a ∈ carrier b ↔ ConjClasses.mk a = b
        theorem mem_carrier_iff_mk_eq {a : α} {b : ConjClasses α} :
    a ∈ carrier ba ∈ 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]
  rfl
        ConjClasses.carrier_eq_preimage_mk
      theorem
     {a : ConjClasses α} : a.carrier = ConjClasses.mk ⁻¹' { a }
        theorem carrier_eq_preimage_mk {a : ConjClasses α} : a.carrier = ConjClasses.mkConjClasses.mk ⁻¹' {a} :=
  Set.ext fun _ => mem_carrier_iff_mk_eq