l3lab/ntp-mathlib huggingface dataset:
@[to_additive]
theorem finprod_eq_single (f : α → M) (a : α) (ha : ∀ x, x ≠ a → f x = 1) :
    ∏ᶠ x, f x = f a := by
  have : mulSupport (f ∘ PLift.down) ⊆ ({PLift.up a} : Finset (PLift α)) := by
    intro x
    contrapose
    simpa [PLift.eq_up_iff_down_eq] using ha x.down
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
a : α
ha : ∀ (x : α), x ≠ a → f x = 1
this : mulSupport (f ∘ PLift.down) ⊆ ↑{{ down := a }}
⊢ ∏ᶠ (x : α), f x = f a

Next tactic:
rw [finprod_eq_prod_plift_of_mulSupport_subset this, Finset.prod_singleton]
@[to_additive]
theorem finprod_eq_dif {p : Prop} [Decidable p] (f : p → M) :
    ∏ᶠ i, f i = if h : p then f h else 1 := by
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝² : CommMonoid M
inst✝¹ : CommMonoid N
p : Prop
inst✝ : Decidable p
f : p → M
⊢ ∏ᶠ (i : p), f i = if h : p then f h else 1

Next tactic:
split_ifs with h
@[to_additive]
theorem finprod_eq_dif {p : Prop} [Decidable p] (f : p → M) :
    ∏ᶠ i, f i = if h : p then f h else 1 := by
  split_ifs with h
  · 

Proof state:
case pos
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝² : CommMonoid M
inst✝¹ : CommMonoid N
p : Prop
inst✝ : Decidable p
f : p → M
h : p
⊢ ∏ᶠ (i : p), f i = f h

Next tactic:
haveI : Unique p := ⟨⟨h⟩, fun _ => rfl⟩
@[to_additive]
theorem finprod_eq_dif {p : Prop} [Decidable p] (f : p → M) :
    ∏ᶠ i, f i = if h : p then f h else 1 := by
  split_ifs with h
  · haveI : Unique p := ⟨⟨h⟩, fun _ => rfl⟩
    

Proof state:
case pos
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝² : CommMonoid M
inst✝¹ : CommMonoid N
p : Prop
inst✝ : Decidable p
f : p → M
h : p
this : Unique p
⊢ ∏ᶠ (i : p), f i = f h

Next tactic:
exact finprod_unique f
@[to_additive]
theorem finprod_eq_dif {p : Prop} [Decidable p] (f : p → M) :
    ∏ᶠ i, f i = if h : p then f h else 1 := by
  split_ifs with h
  · haveI : Unique p := ⟨⟨h⟩, fun _ => rfl⟩
    exact finprod_unique f
  · 

Proof state:
case neg
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝² : CommMonoid M
inst✝¹ : CommMonoid N
p : Prop
inst✝ : Decidable p
f : p → M
h : ¬p
⊢ ∏ᶠ (i : p), f i = 1

Next tactic:
haveI : IsEmpty p := ⟨h⟩
@[to_additive]
theorem finprod_eq_dif {p : Prop} [Decidable p] (f : p → M) :
    ∏ᶠ i, f i = if h : p then f h else 1 := by
  split_ifs with h
  · haveI : Unique p := ⟨⟨h⟩, fun _ => rfl⟩
    exact finprod_unique f
  · haveI : IsEmpty p := ⟨h⟩
    

Proof state:
case neg
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝² : CommMonoid M
inst✝¹ : CommMonoid N
p : Prop
inst✝ : Decidable p
f : p → M
h : ¬p
this : IsEmpty p
⊢ ∏ᶠ (i : p), f i = 1

Next tactic:
exact finprod_of_isEmpty f
@[to_additive (attr := congr)]
theorem finprod_congr_Prop {p q : Prop} {f : p → M} {g : q → M} (hpq : p = q)
    (hfg : ∀ h : q, f (hpq.mpr h) = g h) : finprod f = finprod g := by
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
p q : Prop
f : p → M
g : q → M
hpq : p = q
hfg : ∀ (h : q), f (_ : p) = g h
⊢ finprod f = finprod g

Next tactic:
subst q
@[to_additive (attr := congr)]
theorem finprod_congr_Prop {p q : Prop} {f : p → M} {g : q → M} (hpq : p = q)
    (hfg : ∀ h : q, f (hpq.mpr h) = g h) : finprod f = finprod g := by
  subst q
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
p : Prop
f g : p → M
hfg : ∀ (h : p), f (_ : p) = g h
⊢ finprod f = finprod g

Next tactic:
exact finprod_congr hfg
/-- To prove a property of a finite product, it suffices to prove that the property is
multiplicative and holds on the factors. -/
@[to_additive
      "To prove a property of a finite sum, it suffices to prove that the property is
      additive and holds on the summands."]
theorem finprod_induction {f : α → M} (p : M → Prop) (hp₀ : p 1)
    (hp₁ : ∀ x y, p x → p y → p (x * y)) (hp₂ : ∀ i, p (f i)) : p (∏ᶠ i, f i) := by
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
p : M → Prop
hp₀ : p 1
hp₁ : ∀ (x y : M), p x → p y → p (x * y)
hp₂ : ∀ (i : α), p (f i)
⊢ p (∏ᶠ (i : α), f i)

Next tactic:
rw [finprod]
/-- To prove a property of a finite product, it suffices to prove that the property is
multiplicative and holds on the factors. -/
@[to_additive
      "To prove a property of a finite sum, it suffices to prove that the property is
      additive and holds on the summands."]
theorem finprod_induction {f : α → M} (p : M → Prop) (hp₀ : p 1)
    (hp₁ : ∀ x y, p x → p y → p (x * y)) (hp₂ : ∀ i, p (f i)) : p (∏ᶠ i, f i) := by
  rw [finprod]
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
p : M → Prop
hp₀ : p 1
hp₁ : ∀ (x y : M), p x → p y → p (x * y)
hp₂ : ∀ (i : α), p (f i)
⊢ p (if h : Set.Finite (mulSupport ((fun i => f i) ∘ PLift.down)) then ∏ i in Finite.toFinset h, f i.down else 1)

Next tactic:
split_ifs
/-- To prove a property of a finite product, it suffices to prove that the property is
multiplicative and holds on the factors. -/
@[to_additive
      "To prove a property of a finite sum, it suffices to prove that the property is
      additive and holds on the summands."]
theorem finprod_induction {f : α → M} (p : M → Prop) (hp₀ : p 1)
    (hp₁ : ∀ x y, p x → p y → p (x * y)) (hp₂ : ∀ i, p (f i)) : p (∏ᶠ i, f i) := by
  rw [finprod]
  split_ifs
  

Proof state:
case pos
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
p : M → Prop
hp₀ : p 1
hp₁ : ∀ (x y : M), p x → p y → p (x * y)
hp₂ : ∀ (i : α), p (f i)
h✝ : Set.Finite (mulSupport ((fun i => f i) ∘ PLift.down))
⊢ p (∏ i in Finite.toFinset h✝, f i.down)
case neg
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
p : M → Prop
hp₀ : p 1
hp₁ : ∀ (x y : M), p x → p y → p (x * y)
hp₂ : ∀ (i : α), p (f i)
h✝ : ¬Set.Finite (mulSupport ((fun i => f i) ∘ PLift.down))
⊢ p 1

Next tactic:
exacts [Finset.prod_induction _ _ hp₁ hp₀ fun i _ => hp₂ _, hp₀]
@[to_additive]
theorem MonoidHom.map_finprod_plift (f : M →* N) (g : α → M)
    (h : (mulSupport <| g ∘ PLift.down).Finite) : f (∏ᶠ x, g x) = ∏ᶠ x, f (g x) := by
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
g : α → M
h : Set.Finite (mulSupport (g ∘ PLift.down))
⊢ f (∏ᶠ (x : α), g x) = ∏ᶠ (x : α), f (g x)

Next tactic:
rw [finprod_eq_prod_plift_of_mulSupport_subset h.coe_toFinset.ge,
    finprod_eq_prod_plift_of_mulSupport_subset, map_prod]
@[to_additive]
theorem MonoidHom.map_finprod_plift (f : M →* N) (g : α → M)
    (h : (mulSupport <| g ∘ PLift.down).Finite) : f (∏ᶠ x, g x) = ∏ᶠ x, f (g x) := by
  rw [finprod_eq_prod_plift_of_mulSupport_subset h.coe_toFinset.ge,
    finprod_eq_prod_plift_of_mulSupport_subset, map_prod]
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
g : α → M
h : Set.Finite (mulSupport (g ∘ PLift.down))
⊢ mulSupport ((fun x => f (g x)) ∘ PLift.down) ⊆ ↑(Finite.toFinset h)

Next tactic:
rw [h.coe_toFinset]
@[to_additive]
theorem MonoidHom.map_finprod_plift (f : M →* N) (g : α → M)
    (h : (mulSupport <| g ∘ PLift.down).Finite) : f (∏ᶠ x, g x) = ∏ᶠ x, f (g x) := by
  rw [finprod_eq_prod_plift_of_mulSupport_subset h.coe_toFinset.ge,
    finprod_eq_prod_plift_of_mulSupport_subset, map_prod]
  rw [h.coe_toFinset]
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
g : α → M
h : Set.Finite (mulSupport (g ∘ PLift.down))
⊢ mulSupport ((fun x => f (g x)) ∘ PLift.down) ⊆ mulSupport (g ∘ PLift.down)

Next tactic:
exact mulSupport_comp_subset f.map_one (g ∘ PLift.down)
@[to_additive]
theorem MonoidHom.map_finprod_of_preimage_one (f : M →* N) (hf : ∀ x, f x = 1 → x = 1) (g : α → M) :
    f (∏ᶠ i, g i) = ∏ᶠ i, f (g i) := by
  

Proof state:
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
hf : ∀ (x : M), f x = 1 → x = 1
g : α → M
⊢ f (∏ᶠ (i : α), g i) = ∏ᶠ (i : α), f (g i)

Next tactic:
by_cases hg : (mulSupport <| g ∘ PLift.down).Finite
@[to_additive]
theorem MonoidHom.map_finprod_of_preimage_one (f : M →* N) (hf : ∀ x, f x = 1 → x = 1) (g : α → M) :
    f (∏ᶠ i, g i) = ∏ᶠ i, f (g i) := by
  by_cases hg : (mulSupport <| g ∘ PLift.down).Finite; · 

Proof state:
case pos
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
hf : ∀ (x : M), f x = 1 → x = 1
g : α → M
hg : Set.Finite (mulSupport (g ∘ PLift.down))
⊢ f (∏ᶠ (i : α), g i) = ∏ᶠ (i : α), f (g i)

Next tactic:
exact f.map_finprod_plift g hg
@[to_additive]
theorem MonoidHom.map_finprod_of_preimage_one (f : M →* N) (hf : ∀ x, f x = 1 → x = 1) (g : α → M) :
    f (∏ᶠ i, g i) = ∏ᶠ i, f (g i) := by
  by_cases hg : (mulSupport <| g ∘ PLift.down).Finite; · exact f.map_finprod_plift g hg
  

Proof state:
case neg
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
hf : ∀ (x : M), f x = 1 → x = 1
g : α → M
hg : ¬Set.Finite (mulSupport (g ∘ PLift.down))
⊢ f (∏ᶠ (i : α), g i) = ∏ᶠ (i : α), f (g i)

Next tactic:
rw [finprod, dif_neg, f.map_one, finprod, dif_neg]
@[to_additive]
theorem MonoidHom.map_finprod_of_preimage_one (f : M →* N) (hf : ∀ x, f x = 1 → x = 1) (g : α → M) :
    f (∏ᶠ i, g i) = ∏ᶠ i, f (g i) := by
  by_cases hg : (mulSupport <| g ∘ PLift.down).Finite; · exact f.map_finprod_plift g hg
  rw [finprod, dif_neg, f.map_one, finprod, dif_neg]
  

Proof state:
case neg.hnc
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
hf : ∀ (x : M), f x = 1 → x = 1
g : α → M
hg : ¬Set.Finite (mulSupport (g ∘ PLift.down))
⊢ ¬Set.Finite (mulSupport ((fun i => f (g i)) ∘ PLift.down))
case neg.hnc
G : Type u_1
M : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : M →* N
hf : ∀ (x : M), f x = 1 → x = 1
g : α → M
hg : ¬Set.Finite (mulSupport (g ∘ PLift.down))
⊢ ¬Set.Finite (mulSupport ((fun i => g i) ∘ PLift.down))

Next tactic:
exacts [Infinite.mono (fun x hx => mt (hf (g x.down)) hx) hg, hg]
/-- The `NoZeroSMulDivisors` makes sure that the result holds even when the support of `f` is
infinite. For a more usual version assuming `(support f).Finite` instead, see `finsum_smul'`. -/
theorem finsum_smul {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M]
    (f : ι → R) (x : M) : (∑ᶠ i, f i) • x = ∑ᶠ i, f i • x := by
  

Proof state:
G : Type u_1
M✝ : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝⁵ : CommMonoid M✝
inst✝⁴ : CommMonoid N
R : Type u_7
M : Type u_8
inst✝³ : Ring R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : NoZeroSMulDivisors R M
f : ι → R
x : M
⊢ (∑ᶠ (i : ι), f i) • x = ∑ᶠ (i : ι), f i • x

Next tactic:
rcases eq_or_ne x 0 with (rfl | hx)
/-- The `NoZeroSMulDivisors` makes sure that the result holds even when the support of `f` is
infinite. For a more usual version assuming `(support f).Finite` instead, see `finsum_smul'`. -/
theorem finsum_smul {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M]
    (f : ι → R) (x : M) : (∑ᶠ i, f i) • x = ∑ᶠ i, f i • x := by
  rcases eq_or_ne x 0 with (rfl | hx)
  · 

Proof state:
case inl
G : Type u_1
M✝ : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝⁵ : CommMonoid M✝
inst✝⁴ : CommMonoid N
R : Type u_7
M : Type u_8
inst✝³ : Ring R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : NoZeroSMulDivisors R M
f : ι → R
⊢ (∑ᶠ (i : ι), f i) • 0 = ∑ᶠ (i : ι), f i • 0

Next tactic:
simp
/-- The `NoZeroSMulDivisors` makes sure that the result holds even when the support of `f` is
infinite. For a more usual version assuming `(support f).Finite` instead, see `finsum_smul'`. -/
theorem finsum_smul {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M]
    (f : ι → R) (x : M) : (∑ᶠ i, f i) • x = ∑ᶠ i, f i • x := by
  rcases eq_or_ne x 0 with (rfl | hx)
  · simp
  · 

Proof state:
case inr
G : Type u_1
M✝ : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝⁵ : CommMonoid M✝
inst✝⁴ : CommMonoid N
R : Type u_7
M : Type u_8
inst✝³ : Ring R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : NoZeroSMulDivisors R M
f : ι → R
x : M
hx : x ≠ 0
⊢ (∑ᶠ (i : ι), f i) • x = ∑ᶠ (i : ι), f i • x

Next tactic:
exact ((smulAddHom R M).flip x).map_finsum_of_injective (smul_left_injective R hx) _
/-- The `NoZeroSMulDivisors` makes sure that the result holds even when the support of `f` is
infinite. For a more usual version assuming `(support f).Finite` instead, see `smul_finsum'`. -/
theorem smul_finsum {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M]
    (c : R) (f : ι → M) : (c • ∑ᶠ i, f i) = ∑ᶠ i, c • f i := by
  

Proof state:
G : Type u_1
M✝ : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝⁵ : CommMonoid M✝
inst✝⁴ : CommMonoid N
R : Type u_7
M : Type u_8
inst✝³ : Ring R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : NoZeroSMulDivisors R M
c : R
f : ι → M
⊢ c • ∑ᶠ (i : ι), f i = ∑ᶠ (i : ι), c • f i

Next tactic:
rcases eq_or_ne c 0 with (rfl | hc)
/-- The `NoZeroSMulDivisors` makes sure that the result holds even when the support of `f` is
infinite. For a more usual version assuming `(support f).Finite` instead, see `smul_finsum'`. -/
theorem smul_finsum {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M]
    (c : R) (f : ι → M) : (c • ∑ᶠ i, f i) = ∑ᶠ i, c • f i := by
  rcases eq_or_ne c 0 with (rfl | hc)
  · 

Proof state:
case inl
G : Type u_1
M✝ : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝⁵ : CommMonoid M✝
inst✝⁴ : CommMonoid N
R : Type u_7
M : Type u_8
inst✝³ : Ring R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : NoZeroSMulDivisors R M
f : ι → M
⊢ 0 • ∑ᶠ (i : ι), f i = ∑ᶠ (i : ι), 0 • f i

Next tactic:
simp
/-- The `NoZeroSMulDivisors` makes sure that the result holds even when the support of `f` is
infinite. For a more usual version assuming `(support f).Finite` instead, see `smul_finsum'`. -/
theorem smul_finsum {R M : Type*} [Ring R] [AddCommGroup M] [Module R M] [NoZeroSMulDivisors R M]
    (c : R) (f : ι → M) : (c • ∑ᶠ i, f i) = ∑ᶠ i, c • f i := by
  rcases eq_or_ne c 0 with (rfl | hc)
  · simp
  · 

Proof state:
case inr
G : Type u_1
M✝ : Type u_2
N : Type u_3
α : Sort u_4
β : Sort u_5
ι : Sort u_6
inst✝⁵ : CommMonoid M✝
inst✝⁴ : CommMonoid N
R : Type u_7
M : Type u_8
inst✝³ : Ring R
inst✝² : AddCommGroup M
inst✝¹ : Module R M
inst✝ : NoZeroSMulDivisors R M
c : R
f : ι → M
hc : c ≠ 0
⊢ c • ∑ᶠ (i : ι), f i = ∑ᶠ (i : ι), c • f i

Next tactic:
exact (smulAddHom R M c).map_finsum_of_injective (smul_right_injective M hc) _
@[to_additive]
theorem finprod_eq_mulIndicator_apply (s : Set α) (f : α → M) (a : α) :
    ∏ᶠ _ : a ∈ s, f a = mulIndicator s f a := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
s : Set α
f : α → M
a : α
⊢ ∏ᶠ (_ : a ∈ s), f a = mulIndicator s f a

Next tactic:
classical convert finprod_eq_if (M := M) (p := a ∈ s) (x := f a)
@[to_additive]
theorem finprod_eq_mulIndicator_apply (s : Set α) (f : α → M) (a : α) :
    ∏ᶠ _ : a ∈ s, f a = mulIndicator s f a := by
  classical 

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
s : Set α
f : α → M
a : α
⊢ ∏ᶠ (_ : a ∈ s), f a = mulIndicator s f a

Next tactic:
convert finprod_eq_if (M := M) (p := a ∈ s) (x := f a)
@[to_additive (attr := simp)]
theorem finprod_mem_mulSupport (f : α → M) (a : α) : ∏ᶠ _ : f a ≠ 1, f a = f a := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
a : α
⊢ ∏ᶠ (_ : f a ≠ 1), f a = f a

Next tactic:
rw [← mem_mulSupport, finprod_eq_mulIndicator_apply, mulIndicator_mulSupport]
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
⊢ ∏ᶠ (i : α), f i = ∏ i in s, f i

Next tactic:
have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    exact (Equiv.plift.symm.image_eq_preimage _).symm
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
⊢ mulSupport (f ∘ PLift.down) = ⇑Equiv.plift.symm '' mulSupport f

Next tactic:
rw [mulSupport_comp_eq_preimage]
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
⊢ PLift.down ⁻¹' mulSupport f = ⇑Equiv.plift.symm '' mulSupport f

Next tactic:
exact (Equiv.plift.symm.image_eq_preimage _).symm
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    exact (Equiv.plift.symm.image_eq_preimage _).symm
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
A : mulSupport (f ∘ PLift.down) = ⇑Equiv.plift.symm '' mulSupport f
⊢ ∏ᶠ (i : α), f i = ∏ i in s, f i

Next tactic:
have : mulSupport (f ∘ PLift.down) ⊆ s.map Equiv.plift.symm.toEmbedding := by
    rw [A, Finset.coe_map]
    exact image_subset _ h
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    exact (Equiv.plift.symm.image_eq_preimage _).symm
  have : mulSupport (f ∘ PLift.down) ⊆ s.map Equiv.plift.symm.toEmbedding := by
    

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
A : mulSupport (f ∘ PLift.down) = ⇑Equiv.plift.symm '' mulSupport f
⊢ mulSupport (f ∘ PLift.down) ⊆ ↑(Finset.map (Equiv.toEmbedding Equiv.plift.symm) s)

Next tactic:
rw [A, Finset.coe_map]
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    exact (Equiv.plift.symm.image_eq_preimage _).symm
  have : mulSupport (f ∘ PLift.down) ⊆ s.map Equiv.plift.symm.toEmbedding := by
    rw [A, Finset.coe_map]
    

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
A : mulSupport (f ∘ PLift.down) = ⇑Equiv.plift.symm '' mulSupport f
⊢ ⇑Equiv.plift.symm '' mulSupport f ⊆ ⇑(Equiv.toEmbedding Equiv.plift.symm) '' ↑s

Next tactic:
exact image_subset _ h
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    exact (Equiv.plift.symm.image_eq_preimage _).symm
  have : mulSupport (f ∘ PLift.down) ⊆ s.map Equiv.plift.symm.toEmbedding := by
    rw [A, Finset.coe_map]
    exact image_subset _ h
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
A : mulSupport (f ∘ PLift.down) = ⇑Equiv.plift.symm '' mulSupport f
this : mulSupport (f ∘ PLift.down) ⊆ ↑(Finset.map (Equiv.toEmbedding Equiv.plift.symm) s)
⊢ ∏ᶠ (i : α), f i = ∏ i in s, f i

Next tactic:
rw [finprod_eq_prod_plift_of_mulSupport_subset this]
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    exact (Equiv.plift.symm.image_eq_preimage _).symm
  have : mulSupport (f ∘ PLift.down) ⊆ s.map Equiv.plift.symm.toEmbedding := by
    rw [A, Finset.coe_map]
    exact image_subset _ h
  rw [finprod_eq_prod_plift_of_mulSupport_subset this]
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
A : mulSupport (f ∘ PLift.down) = ⇑Equiv.plift.symm '' mulSupport f
this : mulSupport (f ∘ PLift.down) ⊆ ↑(Finset.map (Equiv.toEmbedding Equiv.plift.symm) s)
⊢ ∏ i in Finset.map (Equiv.toEmbedding Equiv.plift.symm) s, f i.down = ∏ i in s, f i

Next tactic:
simp only [Finset.prod_map, Equiv.coe_toEmbedding]
@[to_additive]
theorem finprod_eq_prod_of_mulSupport_subset (f : α → M) {s : Finset α} (h : mulSupport f ⊆ s) :
    ∏ᶠ i, f i = ∏ i in s, f i := by
  have A : mulSupport (f ∘ PLift.down) = Equiv.plift.symm '' mulSupport f := by
    rw [mulSupport_comp_eq_preimage]
    exact (Equiv.plift.symm.image_eq_preimage _).symm
  have : mulSupport (f ∘ PLift.down) ⊆ s.map Equiv.plift.symm.toEmbedding := by
    rw [A, Finset.coe_map]
    exact image_subset _ h
  rw [finprod_eq_prod_plift_of_mulSupport_subset this]
  simp only [Finset.prod_map, Equiv.coe_toEmbedding]
  

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
A : mulSupport (f ∘ PLift.down) = ⇑Equiv.plift.symm '' mulSupport f
this : mulSupport (f ∘ PLift.down) ⊆ ↑(Finset.map (Equiv.toEmbedding Equiv.plift.symm) s)
⊢ ∏ x in s, f (Equiv.plift.symm x).down = ∏ i in s, f i

Next tactic:
congr
@[to_additive]
theorem finprod_eq_finset_prod_of_mulSupport_subset (f : α → M) {s : Finset α}
    (h : mulSupport f ⊆ (s : Set α)) : ∏ᶠ i, f i = ∏ i in s, f i :=
  haveI h' : (s.finite_toSet.subset h).toFinset ⊆ s := by
    

Proof state:
α : Type u_1
β : Type u_2
ι : Type u_3
G : Type u_4
M : Type u_5
N : Type u_6
inst✝¹ : CommMonoid M
inst✝ : CommMonoid N
f : α → M
s : Finset α
h : mulSupport f ⊆ ↑s
⊢ Finite.toFinset (_ : Set.Finite (mulSupport f)) ⊆ s

Next tactic:
simpa [← Finset.coe_subset, Set.coe_toFinset]