Theorem: Finset.isSquare_prod
File: Mathlib/Algebra/BigOperators/Group/Finset.lean

Proof steps:
state_before: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ IsSquare (∏ i ∈ s, f i)
state_after: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ ∃ c, ∏ i ∈ s, f i = c ^ 2
tactic: rw [isSquare_iff_exists_sq]
state_before: ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ ∃ c, ∏ i ∈ s, f i = c ^ 2
state_after: case h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ ∏ i ∈ s, f i = (∏ x : { x // x ∈ s }, ⋯.choose) ^ 2
tactic: use (∏ (x : s), ((isSquare_iff_exists_sq _).mp (h _ x.2)).choose)
state_before: case h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ ∏ i ∈ s, f i = (∏ x : { x // x ∈ s }, ⋯.choose) ^ 2
state_after: case h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ ∏ i : { x // x ∈ s }, f ↑i = ∏ x : { x // x ∈ s }, ⋯.choose * ⋯.choose
tactic: rw [@sq, ← Finset.prod_mul_distrib, ← Finset.prod_coe_sort]
state_before: case h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ ∏ i : { x // x ∈ s }, f ↑i = ∏ x : { x // x ∈ s }, ⋯.choose * ⋯.choose
state_after: case h.e_f
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ (fun i => f ↑i) = fun x => ⋯.choose * ⋯.choose
tactic: congr
state_before: case h.e_f
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
⊢ (fun i => f ↑i) = fun x => ⋯.choose * ⋯.choose
state_after: case h.e_f.h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
i : { x // x ∈ s }
⊢ f ↑i = ⋯.choose * ⋯.choose
tactic: ext i
state_before: case h.e_f.h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
i : { x // x ∈ s }
⊢ f ↑i = ⋯.choose * ⋯.choose
state_after: case h.e_f.h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
i : { x // x ∈ s }
⊢ f ↑i = ⋯.choose ^ 2
tactic: rw [← @sq]
state_before: case h.e_f.h
ι : Type u_1
κ : Type u_2
α : Type u_3
β : Type u_4
γ : Type u_5
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : CommMonoid β
s : Finset ι
inst✝ : CommMonoid α
f : ι → α
h : ∀ c ∈ s, IsSquare (f c)
i : { x // x ∈ s }
⊢ f ↑i = ⋯.choose ^ 2
state_after: no goals
tactic: exact ((isSquare_iff_exists_sq _).mp (h _ i.2)).choose_spec