l3lab/ntp-mathlib huggingface dataset:
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs (represented as
$n + n + n + n*n$) of commuting elements. -/
@[simps]
def OddCommuteEquiv (hn : Odd n) : { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } ≃
    ZMod n ⊕ ZMod n ⊕ ZMod n ⊕ ZMod n × ZMod n :=
  let u := ZMod.unitOfCoprime 2 (Nat.prime_two.coprime_iff_not_dvd.mpr hn.not_two_dvd_nat)
  have hu : ∀ a : ZMod n, a + a = 0 ↔ a = 0 := fun a => ZMod.add_self_eq_zero_iff_eq_zero hn
  { toFun := fun
      | ⟨⟨sr i, r _⟩, _⟩ => Sum.inl i
      | ⟨⟨r _, sr j⟩, _⟩ => Sum.inr (Sum.inl j)
      | ⟨⟨sr i, sr j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inl (i + j)))
      | ⟨⟨r i, r j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inr ⟨i, j⟩))
    invFun := fun
      | .inl i => ⟨⟨sr i, r 0⟩, congrArg sr ((add_zero i).trans (sub_zero i).symm)⟩
      | .inr (.inl j) => ⟨⟨r 0, sr j⟩, congrArg sr ((sub_zero j).trans (add_zero j).symm)⟩
      | .inr (.inr (.inl k)) => ⟨⟨sr (u⁻¹ * k), sr (u⁻¹ * k)⟩, rfl⟩
      | .inr (.inr (.inr ⟨i, j⟩)) => ⟨⟨r i, r j⟩, congrArg r (add_comm i j)⟩
    left_inv := fun
      | ⟨⟨r i, r j⟩, h⟩ => rfl
      | ⟨⟨r i, sr j⟩, h⟩ => by
        

Proof state:
n : ℕ
hn : Odd n
u : (ZMod n)ˣ := ZMod.unitOfCoprime 2 (_ : Nat.Coprime 2 n)
hu : ∀ (a : ZMod n), a + a = 0 ↔ a = 0
i j : ZMod n
h : Commute (r i, sr j).1 (r i, sr j).2
⊢ (fun x =>
        match x with
        | Sum.inl i => { val := (sr i, r 0), property := (_ : sr (i + 0) = sr (i - 0)) }
        | Sum.inr (Sum.inl j) => { val := (r 0, sr j), property := (_ : sr (j - 0) = sr (j + 0)) }
        | Sum.inr (Sum.inr (Sum.inl k)) =>
          { val := (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)),
            property :=
              (_ :
                (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2 =
                  (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2) }
        | Sum.inr (Sum.inr (Sum.inr (i, j))) => { val := (r i, r j), property := (_ : r (i + j) = r (j + i)) })
      ((fun x =>
          match x with
          | { val := (sr i, r a), property := property } => Sum.inl i
          | { val := (r a, sr j), property := property } => Sum.inr (Sum.inl j)
          | { val := (sr i, sr j), property := property } => Sum.inr (Sum.inr (Sum.inl (i + j)))
          | { val := (r i, r j), property := property } => Sum.inr (Sum.inr (Sum.inr (i, j))))
        { val := (r i, sr j), property := h }) =
    { val := (r i, sr j), property := h }

Next tactic:
simpa [sub_eq_add_neg, neg_eq_iff_add_eq_zero, hu, eq_comm (a := i) (b := 0)] using h.eq
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs (represented as
$n + n + n + n*n$) of commuting elements. -/
@[simps]
def OddCommuteEquiv (hn : Odd n) : { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } ≃
    ZMod n ⊕ ZMod n ⊕ ZMod n ⊕ ZMod n × ZMod n :=
  let u := ZMod.unitOfCoprime 2 (Nat.prime_two.coprime_iff_not_dvd.mpr hn.not_two_dvd_nat)
  have hu : ∀ a : ZMod n, a + a = 0 ↔ a = 0 := fun a => ZMod.add_self_eq_zero_iff_eq_zero hn
  { toFun := fun
      | ⟨⟨sr i, r _⟩, _⟩ => Sum.inl i
      | ⟨⟨r _, sr j⟩, _⟩ => Sum.inr (Sum.inl j)
      | ⟨⟨sr i, sr j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inl (i + j)))
      | ⟨⟨r i, r j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inr ⟨i, j⟩))
    invFun := fun
      | .inl i => ⟨⟨sr i, r 0⟩, congrArg sr ((add_zero i).trans (sub_zero i).symm)⟩
      | .inr (.inl j) => ⟨⟨r 0, sr j⟩, congrArg sr ((sub_zero j).trans (add_zero j).symm)⟩
      | .inr (.inr (.inl k)) => ⟨⟨sr (u⁻¹ * k), sr (u⁻¹ * k)⟩, rfl⟩
      | .inr (.inr (.inr ⟨i, j⟩)) => ⟨⟨r i, r j⟩, congrArg r (add_comm i j)⟩
    left_inv := fun
      | ⟨⟨r i, r j⟩, h⟩ => rfl
      | ⟨⟨r i, sr j⟩, h⟩ => by
        simpa [sub_eq_add_neg, neg_eq_iff_add_eq_zero, hu, eq_comm (a := i) (b := 0)] using h.eq
      | ⟨⟨sr i, r j⟩, h⟩ => by
        

Proof state:
n : ℕ
hn : Odd n
u : (ZMod n)ˣ := ZMod.unitOfCoprime 2 (_ : Nat.Coprime 2 n)
hu : ∀ (a : ZMod n), a + a = 0 ↔ a = 0
i j : ZMod n
h : Commute (sr i, r j).1 (sr i, r j).2
⊢ (fun x =>
        match x with
        | Sum.inl i => { val := (sr i, r 0), property := (_ : sr (i + 0) = sr (i - 0)) }
        | Sum.inr (Sum.inl j) => { val := (r 0, sr j), property := (_ : sr (j - 0) = sr (j + 0)) }
        | Sum.inr (Sum.inr (Sum.inl k)) =>
          { val := (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)),
            property :=
              (_ :
                (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2 =
                  (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2) }
        | Sum.inr (Sum.inr (Sum.inr (i, j))) => { val := (r i, r j), property := (_ : r (i + j) = r (j + i)) })
      ((fun x =>
          match x with
          | { val := (sr i, r a), property := property } => Sum.inl i
          | { val := (r a, sr j), property := property } => Sum.inr (Sum.inl j)
          | { val := (sr i, sr j), property := property } => Sum.inr (Sum.inr (Sum.inl (i + j)))
          | { val := (r i, r j), property := property } => Sum.inr (Sum.inr (Sum.inr (i, j))))
        { val := (sr i, r j), property := h }) =
    { val := (sr i, r j), property := h }

Next tactic:
simpa [sub_eq_add_neg, eq_neg_iff_add_eq_zero, hu, eq_comm (a := j) (b := 0)] using h.eq
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs (represented as
$n + n + n + n*n$) of commuting elements. -/
@[simps]
def OddCommuteEquiv (hn : Odd n) : { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } ≃
    ZMod n ⊕ ZMod n ⊕ ZMod n ⊕ ZMod n × ZMod n :=
  let u := ZMod.unitOfCoprime 2 (Nat.prime_two.coprime_iff_not_dvd.mpr hn.not_two_dvd_nat)
  have hu : ∀ a : ZMod n, a + a = 0 ↔ a = 0 := fun a => ZMod.add_self_eq_zero_iff_eq_zero hn
  { toFun := fun
      | ⟨⟨sr i, r _⟩, _⟩ => Sum.inl i
      | ⟨⟨r _, sr j⟩, _⟩ => Sum.inr (Sum.inl j)
      | ⟨⟨sr i, sr j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inl (i + j)))
      | ⟨⟨r i, r j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inr ⟨i, j⟩))
    invFun := fun
      | .inl i => ⟨⟨sr i, r 0⟩, congrArg sr ((add_zero i).trans (sub_zero i).symm)⟩
      | .inr (.inl j) => ⟨⟨r 0, sr j⟩, congrArg sr ((sub_zero j).trans (add_zero j).symm)⟩
      | .inr (.inr (.inl k)) => ⟨⟨sr (u⁻¹ * k), sr (u⁻¹ * k)⟩, rfl⟩
      | .inr (.inr (.inr ⟨i, j⟩)) => ⟨⟨r i, r j⟩, congrArg r (add_comm i j)⟩
    left_inv := fun
      | ⟨⟨r i, r j⟩, h⟩ => rfl
      | ⟨⟨r i, sr j⟩, h⟩ => by
        simpa [sub_eq_add_neg, neg_eq_iff_add_eq_zero, hu, eq_comm (a := i) (b := 0)] using h.eq
      | ⟨⟨sr i, r j⟩, h⟩ => by
        simpa [sub_eq_add_neg, eq_neg_iff_add_eq_zero, hu, eq_comm (a := j) (b := 0)] using h.eq
      | ⟨⟨sr i, sr j⟩, h⟩ => by
        

Proof state:
n : ℕ
hn : Odd n
u : (ZMod n)ˣ := ZMod.unitOfCoprime 2 (_ : Nat.Coprime 2 n)
hu : ∀ (a : ZMod n), a + a = 0 ↔ a = 0
i j : ZMod n
h : Commute (sr i, sr j).1 (sr i, sr j).2
⊢ (fun x =>
        match x with
        | Sum.inl i => { val := (sr i, r 0), property := (_ : sr (i + 0) = sr (i - 0)) }
        | Sum.inr (Sum.inl j) => { val := (r 0, sr j), property := (_ : sr (j - 0) = sr (j + 0)) }
        | Sum.inr (Sum.inr (Sum.inl k)) =>
          { val := (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)),
            property :=
              (_ :
                (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2 =
                  (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2) }
        | Sum.inr (Sum.inr (Sum.inr (i, j))) => { val := (r i, r j), property := (_ : r (i + j) = r (j + i)) })
      ((fun x =>
          match x with
          | { val := (sr i, r a), property := property } => Sum.inl i
          | { val := (r a, sr j), property := property } => Sum.inr (Sum.inl j)
          | { val := (sr i, sr j), property := property } => Sum.inr (Sum.inr (Sum.inl (i + j)))
          | { val := (r i, r j), property := property } => Sum.inr (Sum.inr (Sum.inr (i, j))))
        { val := (sr i, sr j), property := h }) =
    { val := (sr i, sr j), property := h }

Next tactic:
replace h := r.inj h
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs (represented as
$n + n + n + n*n$) of commuting elements. -/
@[simps]
def OddCommuteEquiv (hn : Odd n) : { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } ≃
    ZMod n ⊕ ZMod n ⊕ ZMod n ⊕ ZMod n × ZMod n :=
  let u := ZMod.unitOfCoprime 2 (Nat.prime_two.coprime_iff_not_dvd.mpr hn.not_two_dvd_nat)
  have hu : ∀ a : ZMod n, a + a = 0 ↔ a = 0 := fun a => ZMod.add_self_eq_zero_iff_eq_zero hn
  { toFun := fun
      | ⟨⟨sr i, r _⟩, _⟩ => Sum.inl i
      | ⟨⟨r _, sr j⟩, _⟩ => Sum.inr (Sum.inl j)
      | ⟨⟨sr i, sr j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inl (i + j)))
      | ⟨⟨r i, r j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inr ⟨i, j⟩))
    invFun := fun
      | .inl i => ⟨⟨sr i, r 0⟩, congrArg sr ((add_zero i).trans (sub_zero i).symm)⟩
      | .inr (.inl j) => ⟨⟨r 0, sr j⟩, congrArg sr ((sub_zero j).trans (add_zero j).symm)⟩
      | .inr (.inr (.inl k)) => ⟨⟨sr (u⁻¹ * k), sr (u⁻¹ * k)⟩, rfl⟩
      | .inr (.inr (.inr ⟨i, j⟩)) => ⟨⟨r i, r j⟩, congrArg r (add_comm i j)⟩
    left_inv := fun
      | ⟨⟨r i, r j⟩, h⟩ => rfl
      | ⟨⟨r i, sr j⟩, h⟩ => by
        simpa [sub_eq_add_neg, neg_eq_iff_add_eq_zero, hu, eq_comm (a := i) (b := 0)] using h.eq
      | ⟨⟨sr i, r j⟩, h⟩ => by
        simpa [sub_eq_add_neg, eq_neg_iff_add_eq_zero, hu, eq_comm (a := j) (b := 0)] using h.eq
      | ⟨⟨sr i, sr j⟩, h⟩ => by
        replace h := r.inj h
        

Proof state:
n : ℕ
hn : Odd n
u : (ZMod n)ˣ := ZMod.unitOfCoprime 2 (_ : Nat.Coprime 2 n)
hu : ∀ (a : ZMod n), a + a = 0 ↔ a = 0
i j : ZMod n
h✝ : Commute (sr i, sr j).1 (sr i, sr j).2
h : j - i = i - j
⊢ (fun x =>
        match x with
        | Sum.inl i => { val := (sr i, r 0), property := (_ : sr (i + 0) = sr (i - 0)) }
        | Sum.inr (Sum.inl j) => { val := (r 0, sr j), property := (_ : sr (j - 0) = sr (j + 0)) }
        | Sum.inr (Sum.inr (Sum.inl k)) =>
          { val := (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)),
            property :=
              (_ :
                (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2 =
                  (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2) }
        | Sum.inr (Sum.inr (Sum.inr (i, j))) => { val := (r i, r j), property := (_ : r (i + j) = r (j + i)) })
      ((fun x =>
          match x with
          | { val := (sr i, r a), property := property } => Sum.inl i
          | { val := (r a, sr j), property := property } => Sum.inr (Sum.inl j)
          | { val := (sr i, sr j), property := property } => Sum.inr (Sum.inr (Sum.inl (i + j)))
          | { val := (r i, r j), property := property } => Sum.inr (Sum.inr (Sum.inr (i, j))))
        { val := (sr i, sr j), property := h✝ }) =
    { val := (sr i, sr j), property := h✝ }

Next tactic:
rw [← neg_sub, neg_eq_iff_add_eq_zero, hu, sub_eq_zero] at h
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs (represented as
$n + n + n + n*n$) of commuting elements. -/
@[simps]
def OddCommuteEquiv (hn : Odd n) : { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } ≃
    ZMod n ⊕ ZMod n ⊕ ZMod n ⊕ ZMod n × ZMod n :=
  let u := ZMod.unitOfCoprime 2 (Nat.prime_two.coprime_iff_not_dvd.mpr hn.not_two_dvd_nat)
  have hu : ∀ a : ZMod n, a + a = 0 ↔ a = 0 := fun a => ZMod.add_self_eq_zero_iff_eq_zero hn
  { toFun := fun
      | ⟨⟨sr i, r _⟩, _⟩ => Sum.inl i
      | ⟨⟨r _, sr j⟩, _⟩ => Sum.inr (Sum.inl j)
      | ⟨⟨sr i, sr j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inl (i + j)))
      | ⟨⟨r i, r j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inr ⟨i, j⟩))
    invFun := fun
      | .inl i => ⟨⟨sr i, r 0⟩, congrArg sr ((add_zero i).trans (sub_zero i).symm)⟩
      | .inr (.inl j) => ⟨⟨r 0, sr j⟩, congrArg sr ((sub_zero j).trans (add_zero j).symm)⟩
      | .inr (.inr (.inl k)) => ⟨⟨sr (u⁻¹ * k), sr (u⁻¹ * k)⟩, rfl⟩
      | .inr (.inr (.inr ⟨i, j⟩)) => ⟨⟨r i, r j⟩, congrArg r (add_comm i j)⟩
    left_inv := fun
      | ⟨⟨r i, r j⟩, h⟩ => rfl
      | ⟨⟨r i, sr j⟩, h⟩ => by
        simpa [sub_eq_add_neg, neg_eq_iff_add_eq_zero, hu, eq_comm (a := i) (b := 0)] using h.eq
      | ⟨⟨sr i, r j⟩, h⟩ => by
        simpa [sub_eq_add_neg, eq_neg_iff_add_eq_zero, hu, eq_comm (a := j) (b := 0)] using h.eq
      | ⟨⟨sr i, sr j⟩, h⟩ => by
        replace h := r.inj h
        rw [← neg_sub, neg_eq_iff_add_eq_zero, hu, sub_eq_zero] at h
        

Proof state:
n : ℕ
hn : Odd n
u : (ZMod n)ˣ := ZMod.unitOfCoprime 2 (_ : Nat.Coprime 2 n)
hu : ∀ (a : ZMod n), a + a = 0 ↔ a = 0
i j : ZMod n
h✝ : Commute (sr i, sr j).1 (sr i, sr j).2
h : i = j
⊢ (fun x =>
        match x with
        | Sum.inl i => { val := (sr i, r 0), property := (_ : sr (i + 0) = sr (i - 0)) }
        | Sum.inr (Sum.inl j) => { val := (r 0, sr j), property := (_ : sr (j - 0) = sr (j + 0)) }
        | Sum.inr (Sum.inr (Sum.inl k)) =>
          { val := (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)),
            property :=
              (_ :
                (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2 =
                  (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).1 * (sr (↑u⁻¹ * k), sr (↑u⁻¹ * k)).2) }
        | Sum.inr (Sum.inr (Sum.inr (i, j))) => { val := (r i, r j), property := (_ : r (i + j) = r (j + i)) })
      ((fun x =>
          match x with
          | { val := (sr i, r a), property := property } => Sum.inl i
          | { val := (r a, sr j), property := property } => Sum.inr (Sum.inl j)
          | { val := (sr i, sr j), property := property } => Sum.inr (Sum.inr (Sum.inl (i + j)))
          | { val := (r i, r j), property := property } => Sum.inr (Sum.inr (Sum.inr (i, j))))
        { val := (sr i, sr j), property := h✝ }) =
    { val := (sr i, sr j), property := h✝ }

Next tactic:
rw [Subtype.ext_iff, Prod.ext_iff, sr.injEq, sr.injEq, h, and_self, ← two_mul]
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs (represented as
$n + n + n + n*n$) of commuting elements. -/
@[simps]
def OddCommuteEquiv (hn : Odd n) : { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } ≃
    ZMod n ⊕ ZMod n ⊕ ZMod n ⊕ ZMod n × ZMod n :=
  let u := ZMod.unitOfCoprime 2 (Nat.prime_two.coprime_iff_not_dvd.mpr hn.not_two_dvd_nat)
  have hu : ∀ a : ZMod n, a + a = 0 ↔ a = 0 := fun a => ZMod.add_self_eq_zero_iff_eq_zero hn
  { toFun := fun
      | ⟨⟨sr i, r _⟩, _⟩ => Sum.inl i
      | ⟨⟨r _, sr j⟩, _⟩ => Sum.inr (Sum.inl j)
      | ⟨⟨sr i, sr j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inl (i + j)))
      | ⟨⟨r i, r j⟩, _⟩ => Sum.inr (Sum.inr (Sum.inr ⟨i, j⟩))
    invFun := fun
      | .inl i => ⟨⟨sr i, r 0⟩, congrArg sr ((add_zero i).trans (sub_zero i).symm)⟩
      | .inr (.inl j) => ⟨⟨r 0, sr j⟩, congrArg sr ((sub_zero j).trans (add_zero j).symm)⟩
      | .inr (.inr (.inl k)) => ⟨⟨sr (u⁻¹ * k), sr (u⁻¹ * k)⟩, rfl⟩
      | .inr (.inr (.inr ⟨i, j⟩)) => ⟨⟨r i, r j⟩, congrArg r (add_comm i j)⟩
    left_inv := fun
      | ⟨⟨r i, r j⟩, h⟩ => rfl
      | ⟨⟨r i, sr j⟩, h⟩ => by
        simpa [sub_eq_add_neg, neg_eq_iff_add_eq_zero, hu, eq_comm (a := i) (b := 0)] using h.eq
      | ⟨⟨sr i, r j⟩, h⟩ => by
        simpa [sub_eq_add_neg, eq_neg_iff_add_eq_zero, hu, eq_comm (a := j) (b := 0)] using h.eq
      | ⟨⟨sr i, sr j⟩, h⟩ => by
        replace h := r.inj h
        rw [← neg_sub, neg_eq_iff_add_eq_zero, hu, sub_eq_zero] at h
        rw [Subtype.ext_iff, Prod.ext_iff, sr.injEq, sr.injEq, h, and_self, ← two_mul]
        

Proof state:
n : ℕ
hn : Odd n
u : (ZMod n)ˣ := ZMod.unitOfCoprime 2 (_ : Nat.Coprime 2 n)
hu : ∀ (a : ZMod n), a + a = 0 ↔ a = 0
i j : ZMod n
h✝ : Commute (sr i, sr j).1 (sr i, sr j).2
h : i = j
⊢ ↑u⁻¹ * (2 * j) = j

Next tactic:
exact u.inv_mul_cancel_left j
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs of commuting elements. -/
lemma card_commute_odd (hn : Odd n) :
    Nat.card { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } = n * (n + 3) := by
  

Proof state:
n : ℕ
hn : Odd n
⊢ Nat.card { p // Commute p.1 p.2 } = n * (n + 3)

Next tactic:
have hn' : NeZero n := ⟨hn.pos.ne'⟩
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs of commuting elements. -/
lemma card_commute_odd (hn : Odd n) :
    Nat.card { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } = n * (n + 3) := by
  have hn' : NeZero n := ⟨hn.pos.ne'⟩
  

Proof state:
n : ℕ
hn : Odd n
hn' : NeZero n
⊢ Nat.card { p // Commute p.1 p.2 } = n * (n + 3)

Next tactic:
simp_rw [Nat.card_congr (OddCommuteEquiv hn), Nat.card_sum, Nat.card_prod, Nat.card_zmod]
/-- If n is odd, then the Dihedral group of order $2n$ has $n(n+3)$ pairs of commuting elements. -/
lemma card_commute_odd (hn : Odd n) :
    Nat.card { p : DihedralGroup n × DihedralGroup n // Commute p.1 p.2 } = n * (n + 3) := by
  have hn' : NeZero n := ⟨hn.pos.ne'⟩
  simp_rw [Nat.card_congr (OddCommuteEquiv hn), Nat.card_sum, Nat.card_prod, Nat.card_zmod]
  

Proof state:
n : ℕ
hn : Odd n
hn' : NeZero n
⊢ n + (n + (n + n * n)) = n * (n + 3)

Next tactic:
ring
lemma card_conjClasses_odd (hn : Odd n) :
    Nat.card (ConjClasses (DihedralGroup n)) = (n + 3) / 2 := by
  

Proof state:
n : ℕ
hn : Odd n
⊢ Nat.card (ConjClasses (DihedralGroup n)) = (n + 3) / 2

Next tactic:
rw [← Nat.mul_div_mul_left _ 2 hn.pos, ← card_commute_odd hn, mul_comm,
    card_comm_eq_card_conjClasses_mul_card, nat_card, Nat.mul_div_left _ (mul_pos two_pos hn.pos)]
instance [CharP R p] : CharP (MvPolynomial σ R) p where
  cast_eq_zero_iff' n := by 

Proof state:
σ : Type u
R : Type v
inst✝¹ : CommSemiring R
p m : ℕ
inst✝ : CharP R p
n : ℕ
⊢ ↑n = 0 ↔ p ∣ n

Next tactic:
rw [← C_eq_coe_nat, ← C_0, C_inj, CharP.cast_eq_zero_iff R p]
instance [CharZero R] : CharZero (MvPolynomial σ R) where
  cast_injective x y hxy := by 

Proof state:
σ : Type u
R : Type v
inst✝¹ : CommSemiring R
p m : ℕ
inst✝ : CharZero R
x y : ℕ
hxy : ↑x = ↑y
⊢ x = y

Next tactic:
rwa [← C_eq_coe_nat, ← C_eq_coe_nat, C_inj, Nat.cast_inj] at hxy
theorem mapRange_eq_map {R S : Type*} [CommSemiring R] [CommSemiring S] (p : MvPolynomial σ R)
    (f : R →+* S) : Finsupp.mapRange f f.map_zero p = map f p := by
  

Proof state:
σ : Type u
R✝ : Type v
inst✝² : CommSemiring R✝
p✝ m : ℕ
R : Type u_1
S : Type u_2
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : R →+* S
⊢ Finsupp.mapRange ⇑f (_ : f 0 = 0) p = (map f) p

Next tactic:
rw [p.as_sum, Finsupp.mapRange_finset_sum, (map f).map_sum]
theorem mapRange_eq_map {R S : Type*} [CommSemiring R] [CommSemiring S] (p : MvPolynomial σ R)
    (f : R →+* S) : Finsupp.mapRange f f.map_zero p = map f p := by
  rw [p.as_sum, Finsupp.mapRange_finset_sum, (map f).map_sum]
  

Proof state:
σ : Type u
R✝ : Type v
inst✝² : CommSemiring R✝
p✝ m : ℕ
R : Type u_1
S : Type u_2
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : R →+* S
⊢ ∑ x in support p, Finsupp.mapRange ⇑f (_ : f 0 = 0) ((monomial x) (coeff x p)) =
    ∑ x in support p, (map f) ((monomial x) (coeff x p))

Next tactic:
refine' Finset.sum_congr rfl fun n _ => _
theorem mapRange_eq_map {R S : Type*} [CommSemiring R] [CommSemiring S] (p : MvPolynomial σ R)
    (f : R →+* S) : Finsupp.mapRange f f.map_zero p = map f p := by
  rw [p.as_sum, Finsupp.mapRange_finset_sum, (map f).map_sum]
  refine' Finset.sum_congr rfl fun n _ => _
  

Proof state:
σ : Type u
R✝ : Type v
inst✝² : CommSemiring R✝
p✝ m : ℕ
R : Type u_1
S : Type u_2
inst✝¹ : CommSemiring R
inst✝ : CommSemiring S
p : MvPolynomial σ R
f : R →+* S
n : σ →₀ ℕ
x✝ : n ∈ support p
⊢ Finsupp.mapRange ⇑f (_ : f 0 = 0) ((monomial n) (coeff n p)) = (map f) ((monomial n) (coeff n p))

Next tactic:
rw [map_monomial, ← single_eq_monomial, Finsupp.mapRange_single, single_eq_monomial]
theorem mem_restrictTotalDegree (p : MvPolynomial σ R) :
    p ∈ restrictTotalDegree σ R m ↔ p.totalDegree ≤ m := by
  

Proof state:
σ : Type u
R : Type v
inst✝ : CommSemiring R
p✝ m : ℕ
p : MvPolynomial σ R
⊢ p ∈ restrictTotalDegree σ R m ↔ totalDegree p ≤ m

Next tactic:
rw [totalDegree, Finset.sup_le_iff]
theorem mem_restrictTotalDegree (p : MvPolynomial σ R) :
    p ∈ restrictTotalDegree σ R m ↔ p.totalDegree ≤ m := by
  rw [totalDegree, Finset.sup_le_iff]
  

Proof state:
σ : Type u
R : Type v
inst✝ : CommSemiring R
p✝ m : ℕ
p : MvPolynomial σ R
⊢ p ∈ restrictTotalDegree σ R m ↔ ∀ b ∈ support p, (Finsupp.sum b fun x e => e) ≤ m

Next tactic:
rfl
theorem mem_restrictDegree (p : MvPolynomial σ R) (n : ℕ) :
    p ∈ restrictDegree σ R n ↔ ∀ s ∈ p.support, ∀ i, (s : σ →₀ ℕ) i ≤ n := by
  

Proof state:
σ : Type u
R : Type v
inst✝ : CommSemiring R
p✝ m : ℕ
p : MvPolynomial σ R
n : ℕ
⊢ p ∈ restrictDegree σ R n ↔ ∀ s ∈ support p, ∀ (i : σ), s i ≤ n

Next tactic:
rw [restrictDegree, Finsupp.mem_supported]
theorem mem_restrictDegree (p : MvPolynomial σ R) (n : ℕ) :
    p ∈ restrictDegree σ R n ↔ ∀ s ∈ p.support, ∀ i, (s : σ →₀ ℕ) i ≤ n := by
  rw [restrictDegree, Finsupp.mem_supported]
  

Proof state:
σ : Type u
R : Type v
inst✝ : CommSemiring R
p✝ m : ℕ
p : MvPolynomial σ R
n : ℕ
⊢ ↑p.support ⊆ {n_1 | ∀ (i : σ), n_1 i ≤ n} ↔ ∀ s ∈ support p, ∀ (i : σ), s i ≤ n

Next tactic:
rfl
theorem mem_restrictDegree_iff_sup [DecidableEq σ] (p : MvPolynomial σ R) (n : ℕ) :
    p ∈ restrictDegree σ R n ↔ ∀ i, p.degrees.count i ≤ n := by
  

Proof state:
σ : Type u
R : Type v
inst✝¹ : CommSemiring R
p✝ m : ℕ
inst✝ : DecidableEq σ
p : MvPolynomial σ R
n : ℕ
⊢ p ∈ restrictDegree σ R n ↔ ∀ (i : σ), Multiset.count i (degrees p) ≤ n

Next tactic:
simp only [mem_restrictDegree, degrees_def, Multiset.count_finset_sup, Finsupp.count_toMultiset,
    Finset.sup_le_iff]
theorem mem_restrictDegree_iff_sup [DecidableEq σ] (p : MvPolynomial σ R) (n : ℕ) :
    p ∈ restrictDegree σ R n ↔ ∀ i, p.degrees.count i ≤ n := by
  simp only [mem_restrictDegree, degrees_def, Multiset.count_finset_sup, Finsupp.count_toMultiset,
    Finset.sup_le_iff]
  

Proof state:
σ : Type u
R : Type v
inst✝¹ : CommSemiring R
p✝ m : ℕ
inst✝ : DecidableEq σ
p : MvPolynomial σ R
n : ℕ
⊢ (∀ s ∈ support p, ∀ (i : σ), s i ≤ n) ↔ ∀ (i : σ), ∀ b ∈ support p, b i ≤ n

Next tactic:
exact ⟨fun h n s hs => h s hs n, fun h s hs n => h n s hs⟩
/-- Equivalence between continuous maps into the units of a monoid with continuous multiplication
and the units of the monoid of continuous maps. -/
-- porting note: `simps` made bad `simp` lemmas (LHS simplifies) so we add them manually below
@[to_additive (attr := simps apply_val_apply symm_apply_apply_val)
"Equivalence between continuous maps into the additive units of an additive monoid with continuous
addition and the additive units of the additive monoid of continuous maps."]
def unitsLift : C(X, Mˣ) ≃ C(X, M)ˣ where
  toFun f :=
    { val := ⟨fun x => f x, Units.continuous_val.comp f.continuous⟩
      inv := ⟨fun x => ↑(f x)⁻¹, Units.continuous_val.comp (continuous_inv.comp f.continuous)⟩
      val_inv := ext fun x => Units.mul_inv _
      inv_val := ext fun x => Units.inv_mul _ }
  invFun f :=
    { toFun := fun x =>
        ⟨(f : C(X, M)) x, (↑f⁻¹ : C(X, M)) x,
          ContinuousMap.congr_fun f.mul_inv x, ContinuousMap.congr_fun f.inv_mul x⟩
      continuous_toFun := continuous_induced_rng.2 <|
        (f : C(X, M)).continuous.prod_mk <|
        MulOpposite.continuous_op.comp (↑f⁻¹ : C(X, M)).continuous }
  left_inv f := by 

Proof state:
X : Type u_1
M : Type u_2
R : Type u_3
𝕜 : Type u_4
inst✝³ : TopologicalSpace X
inst✝² : Monoid M
inst✝¹ : TopologicalSpace M
inst✝ : ContinuousMul M
f : C(X, Mˣ)
⊢ (fun f =>
        mk fun x =>
          { val := ↑f x, inv := ↑f⁻¹ x, val_inv := (_ : (↑f * ↑f⁻¹) x = 1 x), inv_val := (_ : (↑f⁻¹ * ↑f) x = 1 x) })
      ((fun f =>
          { val := mk fun x => ↑(f x), inv := mk fun x => ↑(f x)⁻¹,
            val_inv := (_ : ((mk fun x => ↑(f x)) * mk fun x => ↑(f x)⁻¹) = 1),
            inv_val := (_ : ((mk fun x => ↑(f x)⁻¹) * mk fun x => ↑(f x)) = 1) })
        f) =
    f

Next tactic:
ext