Theorem: sum_hom_units_eq_zero
File: Mathlib/RingTheory/IntegralDomain.lean

tactic: obtain ⟨x, hx⟩ :
  ∃ x : MonoidHom.range f.toHomUnits,
    ∀ y : MonoidHom.range f.toHomUnits, y ∈ Submonoid.powers x
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
⊢ ∑ g : G, ↑f g = 0

tactic: exact IsCyclic.exists_monoid_generator
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
⊢ ∃ x, ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x

case intro
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
⊢ ∑ g : G, ↑f g = 0

tactic: have hx1 : x ≠ 1 := by
  rintro rfl
  apply hf
  ext g
  rw [MonoidHom.one_apply]
  cases' hx ⟨f.toHomUnits g, g, rfl⟩ with n hn
  rwa [Subtype.ext_iff, Units.ext_iff, Subtype.coe_mk, MonoidHom.coe_toHomUnits, one_pow,
    eq_comm] at hn
state_before: case intro
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
⊢ ∑ g : G, ↑f g = 0

tactic: replace hx1 : (x.val : R) - 1 ≠ 0
state_before: case intro
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : x ≠ 1
⊢ ∑ g : G, ↑f g = 0

tactic: exact fun h => hx1 (Subtype.eq (Units.ext (sub_eq_zero.1 h)))
state_before: case hx1
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : x ≠ 1
⊢ ↑↑x - 1 ≠ 0

case intro
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
⊢ ∑ g : G, ↑f g = 0

tactic: let c := (univ.filter fun g => f.toHomUnits g = 1).card
state_before: case intro
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
⊢ ∑ g : G, ↑f g = 0

tactic: calc
  (∑ g : G, f g) = ∑ g : G, (f.toHomUnits g : R) := rfl
  _ = ∑ u : Rˣ in univ.image f.toHomUnits,
        (univ.filter fun g => f.toHomUnits g = u).card • (u : R) :=
    (sum_comp ((↑) : Rˣ → R) f.toHomUnits)
  _ = ∑ u : Rˣ in univ.image f.toHomUnits, c • (u : R) :=
    (sum_congr rfl fun u hu => congr_arg₂ _ ?_ rfl)
  _ = ∑ b : MonoidHom.range f.toHomUnits, c • ((b : Rˣ) : R) :=
    (Finset.sum_subtype _ (by simp) _)
  _ = c • ∑ b : MonoidHom.range f.toHomUnits, ((b : Rˣ) : R) := smul_sum.symm
  _ = c • (0 : R) := (congr_arg₂ _ rfl ?_)
  _ = (0 : R) := smul_zero _
state_before: case intro
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ∑ g : G, ↑f g = 0

tactic: show (∑ b : MonoidHom.range f.toHomUnits, ((b : Rˣ) : R)) = 0
state_before: case intro.calc_2
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ∑ b : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }, ↑↑b = 0

tactic: calc
  (∑ b : MonoidHom.range f.toHomUnits, ((b : Rˣ) : R))
    = ∑ n in range (orderOf x), ((x : Rˣ) : R) ^ n :=
    Eq.symm <|
      sum_bij (fun n _ => x ^ n) (by simp only [mem_univ, forall_true_iff])
        (by simp only [imp_true_iff, eq_self_iff_true, Subgroup.coe_pow,
            Units.val_pow_eq_pow_val])
        (fun m n hm hn =>
          pow_injective_of_lt_orderOf _ (by simpa only [mem_range] using hm)
            (by simpa only [mem_range] using hn))
        (fun b _ => let ⟨n, hn⟩ := hx b
          ⟨n % orderOf x, mem_range.2 (Nat.mod_lt _ (orderOf_pos _)),
           by dsimp at hn ⊢; rw [← pow_eq_mod_orderOf, hn]⟩)
  _ = 0 := ?_
state_before: case intro.calc_2
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ∑ b : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }, ↑↑b = 0

tactic: rw [← mul_left_inj' hx1, MulZeroClass.zero_mul, geom_sum_mul]
state_before: case intro.calc_2
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ∑ n in range (orderOf x), ↑↑x ^ n = 0

tactic: norm_cast
state_before: case intro.calc_2
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ↑↑x ^ orderOf x - 1 = 0

tactic: simp [pow_orderOf_eq_one]
state_before: case intro.calc_2
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ↑↑(x ^ orderOf x) - 1 = 0

tactic: rintro rfl
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
⊢ x ≠ 1

tactic: apply hf
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers 1
⊢ False

tactic: ext g
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers 1
⊢ f = 1

tactic: rw [MonoidHom.one_apply]
state_before: case h
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers 1
g : G
⊢ ↑f g = ↑1 g

tactic: cases' hx ⟨f.toHomUnits g, g, rfl⟩ with n hn
state_before: case h
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers 1
g : G
⊢ ↑f g = 1

tactic: rwa [Subtype.ext_iff, Units.ext_iff, Subtype.coe_mk, MonoidHom.coe_toHomUnits, one_pow,
  eq_comm] at hn
state_before: case h.intro
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers 1
g : G
n : ℕ
hn :
  (fun x x_1 => x ^ x_1) 1 n =
    { val := ↑(MonoidHom.toHomUnits f) g,
      property := (_ : ∃ y, ↑(MonoidHom.toHomUnits f) y = ↑(MonoidHom.toHomUnits f) g) }
⊢ ↑f g = 1

tactic: simp
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ∀ (x : Rˣ), x ∈ image (↑(MonoidHom.toHomUnits f)) univ ↔ x ∈ MonoidHom.range (MonoidHom.toHomUnits f)

tactic: show (univ.filter fun g : G => f.toHomUnits g = u).card = c
state_before: case intro.calc_1
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
u : Rˣ
hu : u ∈ image (↑(MonoidHom.toHomUnits f)) univ
⊢ card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = u) univ) = c

tactic: apply card_fiber_eq_of_mem_range f.toHomUnits
state_before: case intro.calc_1
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
u : Rˣ
hu : u ∈ image (↑(MonoidHom.toHomUnits f)) univ
⊢ card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = u) univ) = c

tactic: simpa only [mem_image, mem_univ, true_and, Set.mem_range] using hu
state_before: case intro.calc_1.hx
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
u : Rˣ
hu : u ∈ image (↑(MonoidHom.toHomUnits f)) univ
⊢ u ∈ Set.range ↑(MonoidHom.toHomUnits f)

tactic: exact ⟨1, f.toHomUnits.map_one⟩
state_before: case intro.calc_1.hy
R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
u : Rˣ
hu : u ∈ image (↑(MonoidHom.toHomUnits f)) univ
⊢ 1 ∈ Set.range ↑(MonoidHom.toHomUnits f)

tactic: simp only [mem_univ, forall_true_iff]
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ∀ (a : ℕ) (ha : a ∈ range (orderOf x)), (fun n x_1 => x ^ n) a ha ∈ univ

tactic: simp only [imp_true_iff, eq_self_iff_true, Subgroup.coe_pow,
Units.val_pow_eq_pow_val]
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
⊢ ∀ (a : ℕ) (ha : a ∈ range (orderOf x)), ↑↑x ^ a = ↑↑((fun n x_1 => x ^ n) a ha)

tactic: simpa only [mem_range] using hm
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
m n : ℕ
hm : m ∈ range (orderOf x)
hn : n ∈ range (orderOf x)
⊢ m < orderOf x

tactic: simpa only [mem_range] using hn
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
m n : ℕ
hm : m ∈ range (orderOf x)
hn : n ∈ range (orderOf x)
⊢ n < orderOf x

tactic: dsimp at hn ⊢
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
b : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
x✝ : b ∈ univ
n : ℕ
hn : (fun x x_1 => x ^ x_1) x n = b
⊢ b = (fun n x_1 => x ^ n) (n % orderOf x) (_ : n % orderOf x ∈ range (orderOf x))

tactic: rw [← pow_eq_mod_orderOf, hn]
state_before: R : Type u_2
G : Type u_1
inst✝³ : CommRing R
inst✝² : IsDomain R
inst✝¹ : Group G
inst✝ : Fintype G
f : G →* R
hf : f ≠ 1
x : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
hx : ∀ (y : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }), y ∈ Submonoid.powers x
hx1 : ↑↑x - 1 ≠ 0
c : ℕ := card (filter (fun g => ↑(MonoidHom.toHomUnits f) g = 1) univ)
b : { x // x ∈ MonoidHom.range (MonoidHom.toHomUnits f) }
x✝ : b ∈ univ
n : ℕ
hn : x ^ n = b
⊢ b = x ^ (n % orderOf x)