Theorem: Finset.multiplicativeEnergy_univ_left
File: Mathlib/Combinatorics/Additive/Energy.lean

tactic: simp only [multiplicativeEnergy, univ_product_univ, Fintype.card, sq, ← card_product]
state_before: α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
⊢ multiplicativeEnergy univ t = Fintype.card α * card t ^ 2

tactic: let f : α × α × α → (α × α) × α × α := fun x => ((x.1 * x.2.2, x.1 * x.2.1), x.2)
state_before: α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
⊢ card (filter (fun x => x.fst.fst * x.snd.fst = x.fst.snd * x.snd.snd) (univ ×ˢ t ×ˢ t)) = card (univ ×ˢ t ×ˢ t)

tactic: 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]
state_before: α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
⊢ card (filter (fun x => x.fst.fst * x.snd.fst = x.fst.snd * x.snd.snd) (univ ×ˢ t ×ˢ t)) = card (univ ×ˢ t ×ˢ t)

tactic: rw [← card_image_of_injOn this]
state_before: α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
⊢ card (filter (fun x => x.fst.fst * x.snd.fst = x.fst.snd * x.snd.snd) (univ ×ˢ t ×ˢ t)) = card (univ ×ˢ t ×ˢ t)

tactic: congr with a
state_before: α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
⊢ card (filter (fun x => x.fst.fst * x.snd.fst = x.fst.snd * x.snd.snd) (univ ×ˢ t ×ˢ t)) =
    card (image f (univ ×ˢ t ×ˢ t))

tactic: simp only [mem_filter, mem_product, mem_univ, true_and_iff, mem_image, exists_prop,
  Prod.exists]
state_before: case e_s.a
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
a : (α × α) × α × α
⊢ a ∈ filter (fun x => x.fst.fst * x.snd.fst = x.fst.snd * x.snd.snd) (univ ×ˢ t ×ˢ t) ↔ a ∈ image f (univ ×ˢ t ×ˢ t)

tactic: refine' ⟨fun h => ⟨a.1.1 * a.2.2⁻¹, _, _, h.1, by simp [mul_right_comm, h.2]⟩, _⟩
state_before: case e_s.a
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
a : (α × α) × α × α
⊢ (a.snd.fst ∈ t ∧ a.snd.snd ∈ t) ∧ a.fst.fst * a.snd.fst = a.fst.snd * a.snd.snd ↔
    ∃ a_1 a_2 b, (a_2 ∈ t ∧ b ∈ t) ∧ ((a_1 * b, a_1 * a_2), a_2, b) = a

tactic: rintro ⟨b, c, d, hcd, rfl⟩
state_before: case e_s.a
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
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.snd.fst ∈ t ∧ a.snd.snd ∈ t) ∧ a.fst.fst * a.snd.fst = a.fst.snd * a.snd.snd

tactic: simpa [mul_right_comm]
state_before: case e_s.a.intro.intro.intro.intro
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
b c d : α
hcd : c ∈ t ∧ d ∈ t
⊢ (((b * d, b * c), c, d).snd.fst ∈ t ∧ ((b * d, b * c), c, d).snd.snd ∈ t) ∧
    ((b * d, b * c), c, d).fst.fst * ((b * d, b * c), c, d).snd.fst =
      ((b * d, b * c), c, d).fst.snd * ((b * d, b * c), c, d).snd.snd

tactic: rintro ⟨a₁, b₁, c₁⟩ _ ⟨a₂, b₂, c₂⟩ h₂ h
state_before: α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
⊢ Set.InjOn f ↑(univ ×ˢ t ×ˢ t)

tactic: simp_rw [Prod.ext_iff] at h
state_before: case mk.mk.mk.mk
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
a₁ b₁ c₁ : α
a✝ : (a₁, b₁, c₁) ∈ ↑(univ ×ˢ t ×ˢ t)
a₂ b₂ c₂ : α
h₂ : (a₂, b₂, c₂) ∈ ↑(univ ×ˢ t ×ˢ t)
h : f (a₁, b₁, c₁) = f (a₂, b₂, c₂)
⊢ (a₁, b₁, c₁) = (a₂, b₂, c₂)

tactic: obtain ⟨h, rfl, rfl⟩ := h
state_before: case mk.mk.mk.mk
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
a₁ b₁ c₁ : α
a✝ : (a₁, b₁, c₁) ∈ ↑(univ ×ˢ t ×ˢ t)
a₂ b₂ c₂ : α
h₂ : (a₂, b₂, c₂) ∈ ↑(univ ×ˢ t ×ˢ t)
h : (a₁ * c₁ = a₂ * c₂ ∧ a₁ * b₁ = a₂ * b₂) ∧ b₁ = b₂ ∧ c₁ = c₂
⊢ (a₁, b₁, c₁) = (a₂, b₂, c₂)

tactic: rw [mul_right_cancel h.1]
state_before: case mk.mk.mk.mk.intro.intro
α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
a₁ b₁ c₁ : α
a✝ : (a₁, b₁, c₁) ∈ ↑(univ ×ˢ t ×ˢ t)
a₂ : α
h₂ : (a₂, b₁, c₁) ∈ ↑(univ ×ˢ t ×ˢ t)
h : a₁ * c₁ = a₂ * c₁ ∧ a₁ * b₁ = a₂ * b₁
⊢ (a₁, b₁, c₁) = (a₂, b₁, c₁)

tactic: simp [mul_right_comm, h.2]
state_before: α : Type u_1
inst✝² : DecidableEq α
inst✝¹ : CommGroup α
inst✝ : Fintype α
s t : Finset α
f : α × α × α → (α × α) × α × α := fun x => ((x.fst * x.snd.snd, x.fst * x.snd.fst), x.snd)
this : Set.InjOn f ↑(univ ×ˢ t ×ˢ t)
a : (α × α) × α × α
h : (a.snd.fst ∈ t ∧ a.snd.snd ∈ t) ∧ a.fst.fst * a.snd.fst = a.fst.snd * a.snd.snd
⊢ ((a.fst.fst * a.snd.snd⁻¹ * a.snd.snd, a.fst.fst * a.snd.snd⁻¹ * a.snd.fst), a.snd.fst, a.snd.snd) = a