l3lab/ntp-mathlib huggingface dataset:
theorem splittingOfFunOnFintypeSurjective_splits [Fintype α] (f : M →ₗ[R] α → R)
    (s : Surjective f) : f.comp (splittingOfFunOnFintypeSurjective f s) = LinearMap.id := by
  classical
  -- Porting note: `ext` can't find appropriate theorems.
  refine pi_ext' fun x => ext_ring <| funext fun y => ?_
  dsimp [splittingOfFunOnFintypeSurjective]
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : Semiring R
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R M
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
α : Type u_4
inst✝ : Fintype α
f : M →ₗ[R] α → R
s : Surjective ⇑f
x y : α
⊢ f
      (sum ((LinearEquiv.symm (linearEquivFunOnFinite R R α)) (Pi.single x 1)) fun x r =>
        r • Exists.choose (_ : ∃ a, f a = ⇑fun₀ | x => 1))
      y =
    Pi.single x 1 y

Next tactic:
rw [linearEquivFunOnFinite_symm_single, Finsupp.sum_single_index, one_smul,
    (s (Finsupp.single x 1)).choose_spec, Finsupp.single_eq_pi_single]
theorem splittingOfFunOnFintypeSurjective_splits [Fintype α] (f : M →ₗ[R] α → R)
    (s : Surjective f) : f.comp (splittingOfFunOnFintypeSurjective f s) = LinearMap.id := by
  classical
  -- Porting note: `ext` can't find appropriate theorems.
  refine pi_ext' fun x => ext_ring <| funext fun y => ?_
  dsimp [splittingOfFunOnFintypeSurjective]
  rw [linearEquivFunOnFinite_symm_single, Finsupp.sum_single_index, one_smul,
    (s (Finsupp.single x 1)).choose_spec, Finsupp.single_eq_pi_single]
  

Proof state:
R : Type u_1
M : Type u_2
N : Type u_3
inst✝⁵ : Semiring R
inst✝⁴ : AddCommMonoid M
inst✝³ : Module R M
inst✝² : AddCommMonoid N
inst✝¹ : Module R N
α : Type u_4
inst✝ : Fintype α
f : M →ₗ[R] α → R
s : Surjective ⇑f
x y : α
⊢ 0 • Exists.choose (_ : ∃ a, f a = ⇑fun₀ | x => 1) = 0

Next tactic:
rw [zero_smul]
theorem HasDerivAt.eventually_ne (h : HasDerivAt f f' x) (hf' : f' ≠ 0) :
    ∀ᶠ z in 𝓝[≠] x, f z ≠ f x :=
  (hasDerivAt_iff_hasFDerivAt.1 h).eventually_ne
    ⟨‖f'‖⁻¹, fun z => by 

Proof state:
𝕜 : Type u
inst✝⁴ : NontriviallyNormedField 𝕜
F : Type v
inst✝³ : NormedAddCommGroup F
inst✝² : NormedSpace 𝕜 F
E : Type w
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f f₀ f₁ g : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L L₁ L₂ : Filter 𝕜
h : HasDerivAt f f' x
hf' : f' ≠ 0
z : 𝕜
⊢ ‖z‖ ≤ ‖f'‖⁻¹ * ‖(ContinuousLinearMap.smulRight 1 f') z‖

Next tactic:
field_simp [norm_smul, mt norm_eq_zero.1 hf']
theorem not_differentiableWithinAt_of_local_left_inverse_hasDerivWithinAt_zero {f g : 𝕜 → 𝕜} {a : 𝕜}
    {s t : Set 𝕜} (ha : a ∈ s) (hsu : UniqueDiffWithinAt 𝕜 s a) (hf : HasDerivWithinAt f 0 t (g a))
    (hst : MapsTo g s t) (hfg : f ∘ g =ᶠ[𝓝[s] a] id) : ¬DifferentiableWithinAt 𝕜 g s a := by
  

Proof state:
𝕜 : Type u
inst✝⁴ : NontriviallyNormedField 𝕜
F : Type v
inst✝³ : NormedAddCommGroup F
inst✝² : NormedSpace 𝕜 F
E : Type w
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f✝ f₀ f₁ g✝ : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s✝ t✝ : Set 𝕜
L L₁ L₂ : Filter 𝕜
f g : 𝕜 → 𝕜
a : 𝕜
s t : Set 𝕜
ha : a ∈ s
hsu : UniqueDiffWithinAt 𝕜 s a
hf : HasDerivWithinAt f 0 t (g a)
hst : MapsTo g s t
hfg : f ∘ g =ᶠ[𝓝[s] a] id
⊢ ¬DifferentiableWithinAt 𝕜 g s a

Next tactic:
intro hg
theorem not_differentiableWithinAt_of_local_left_inverse_hasDerivWithinAt_zero {f g : 𝕜 → 𝕜} {a : 𝕜}
    {s t : Set 𝕜} (ha : a ∈ s) (hsu : UniqueDiffWithinAt 𝕜 s a) (hf : HasDerivWithinAt f 0 t (g a))
    (hst : MapsTo g s t) (hfg : f ∘ g =ᶠ[𝓝[s] a] id) : ¬DifferentiableWithinAt 𝕜 g s a := by
  intro hg
  

Proof state:
𝕜 : Type u
inst✝⁴ : NontriviallyNormedField 𝕜
F : Type v
inst✝³ : NormedAddCommGroup F
inst✝² : NormedSpace 𝕜 F
E : Type w
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f✝ f₀ f₁ g✝ : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s✝ t✝ : Set 𝕜
L L₁ L₂ : Filter 𝕜
f g : 𝕜 → 𝕜
a : 𝕜
s t : Set 𝕜
ha : a ∈ s
hsu : UniqueDiffWithinAt 𝕜 s a
hf : HasDerivWithinAt f 0 t (g a)
hst : MapsTo g s t
hfg : f ∘ g =ᶠ[𝓝[s] a] id
hg : DifferentiableWithinAt 𝕜 g s a
⊢ False

Next tactic:
have := (hf.comp a hg.hasDerivWithinAt hst).congr_of_eventuallyEq_of_mem hfg.symm ha
theorem not_differentiableWithinAt_of_local_left_inverse_hasDerivWithinAt_zero {f g : 𝕜 → 𝕜} {a : 𝕜}
    {s t : Set 𝕜} (ha : a ∈ s) (hsu : UniqueDiffWithinAt 𝕜 s a) (hf : HasDerivWithinAt f 0 t (g a))
    (hst : MapsTo g s t) (hfg : f ∘ g =ᶠ[𝓝[s] a] id) : ¬DifferentiableWithinAt 𝕜 g s a := by
  intro hg
  have := (hf.comp a hg.hasDerivWithinAt hst).congr_of_eventuallyEq_of_mem hfg.symm ha
  

Proof state:
𝕜 : Type u
inst✝⁴ : NontriviallyNormedField 𝕜
F : Type v
inst✝³ : NormedAddCommGroup F
inst✝² : NormedSpace 𝕜 F
E : Type w
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f✝ f₀ f₁ g✝ : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s✝ t✝ : Set 𝕜
L L₁ L₂ : Filter 𝕜
f g : 𝕜 → 𝕜
a : 𝕜
s t : Set 𝕜
ha : a ∈ s
hsu : UniqueDiffWithinAt 𝕜 s a
hf : HasDerivWithinAt f 0 t (g a)
hst : MapsTo g s t
hfg : f ∘ g =ᶠ[𝓝[s] a] id
hg : DifferentiableWithinAt 𝕜 g s a
this : HasDerivWithinAt id (0 * derivWithin g s a) s a
⊢ False

Next tactic:
simpa using hsu.eq_deriv _ this (hasDerivWithinAt_id _ _)
theorem not_differentiableAt_of_local_left_inverse_hasDerivAt_zero {f g : 𝕜 → 𝕜} {a : 𝕜}
    (hf : HasDerivAt f 0 (g a)) (hfg : f ∘ g =ᶠ[𝓝 a] id) : ¬DifferentiableAt 𝕜 g a := by
  

Proof state:
𝕜 : Type u
inst✝⁴ : NontriviallyNormedField 𝕜
F : Type v
inst✝³ : NormedAddCommGroup F
inst✝² : NormedSpace 𝕜 F
E : Type w
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f✝ f₀ f₁ g✝ : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L L₁ L₂ : Filter 𝕜
f g : 𝕜 → 𝕜
a : 𝕜
hf : HasDerivAt f 0 (g a)
hfg : f ∘ g =ᶠ[𝓝 a] id
⊢ ¬DifferentiableAt 𝕜 g a

Next tactic:
intro hg
theorem not_differentiableAt_of_local_left_inverse_hasDerivAt_zero {f g : 𝕜 → 𝕜} {a : 𝕜}
    (hf : HasDerivAt f 0 (g a)) (hfg : f ∘ g =ᶠ[𝓝 a] id) : ¬DifferentiableAt 𝕜 g a := by
  intro hg
  

Proof state:
𝕜 : Type u
inst✝⁴ : NontriviallyNormedField 𝕜
F : Type v
inst✝³ : NormedAddCommGroup F
inst✝² : NormedSpace 𝕜 F
E : Type w
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f✝ f₀ f₁ g✝ : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L L₁ L₂ : Filter 𝕜
f g : 𝕜 → 𝕜
a : 𝕜
hf : HasDerivAt f 0 (g a)
hfg : f ∘ g =ᶠ[𝓝 a] id
hg : DifferentiableAt 𝕜 g a
⊢ False

Next tactic:
have := (hf.comp a hg.hasDerivAt).congr_of_eventuallyEq hfg.symm
theorem not_differentiableAt_of_local_left_inverse_hasDerivAt_zero {f g : 𝕜 → 𝕜} {a : 𝕜}
    (hf : HasDerivAt f 0 (g a)) (hfg : f ∘ g =ᶠ[𝓝 a] id) : ¬DifferentiableAt 𝕜 g a := by
  intro hg
  have := (hf.comp a hg.hasDerivAt).congr_of_eventuallyEq hfg.symm
  

Proof state:
𝕜 : Type u
inst✝⁴ : NontriviallyNormedField 𝕜
F : Type v
inst✝³ : NormedAddCommGroup F
inst✝² : NormedSpace 𝕜 F
E : Type w
inst✝¹ : NormedAddCommGroup E
inst✝ : NormedSpace 𝕜 E
f✝ f₀ f₁ g✝ : 𝕜 → F
f' f₀' f₁' g' : F
x : 𝕜
s t : Set 𝕜
L L₁ L₂ : Filter 𝕜
f g : 𝕜 → 𝕜
a : 𝕜
hf : HasDerivAt f 0 (g a)
hfg : f ∘ g =ᶠ[𝓝 a] id
hg : DifferentiableAt 𝕜 g a
this : HasDerivAt id (0 * deriv g a) a
⊢ False

Next tactic:
simpa using this.unique (hasDerivAt_id a)
@[to_additive (attr := simp)]
theorem prod_val [CommMonoid α] (s : Finset α) : s.1.prod = s.prod id := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
inst✝ : CommMonoid α
s : Finset α
⊢ Multiset.prod s.val = Finset.prod s id

Next tactic:
rw [Finset.prod, Multiset.map_id]
@[simp]
theorem sum_multiset_singleton (s : Finset α) : (s.sum fun x => {x}) = s.val := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
s : Finset α
⊢ ∑ x in s, {x} = s.val

Next tactic:
simp only [sum_eq_multiset_sum, Multiset.sum_map_singleton]
@[to_additive (attr := simp)]
theorem map_prod [CommMonoid β] [CommMonoid γ] {G : Type*} [MonoidHomClass G β γ] (g : G)
    (f : α → β) (s : Finset α) : g (∏ x in s, f x) = ∏ x in s, g (f x) := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
inst✝² : CommMonoid β
inst✝¹ : CommMonoid γ
G : Type u_2
inst✝ : MonoidHomClass G β γ
g : G
f : α → β
s : Finset α
⊢ g (∏ x in s, f x) = ∏ x in s, g (f x)

Next tactic:
simp only [Finset.prod_eq_multiset_prod, map_multiset_prod, Multiset.map_map]
@[to_additive (attr := simp)]
theorem map_prod [CommMonoid β] [CommMonoid γ] {G : Type*} [MonoidHomClass G β γ] (g : G)
    (f : α → β) (s : Finset α) : g (∏ x in s, f x) = ∏ x in s, g (f x) := by
  simp only [Finset.prod_eq_multiset_prod, map_multiset_prod, Multiset.map_map]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
inst✝² : CommMonoid β
inst✝¹ : CommMonoid γ
G : Type u_2
inst✝ : MonoidHomClass G β γ
g : G
f : α → β
s : Finset α
⊢ Multiset.prod (Multiset.map (⇑g ∘ fun x => f x) s.val) = Multiset.prod (Multiset.map (fun x => g (f x)) s.val)

Next tactic:
rfl
@[to_additive]
theorem prod_of_empty [IsEmpty α] (s : Finset α) : ∏ i in s, f i = 1 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : IsEmpty α
s : Finset α
⊢ ∏ i in s, f i = 1

Next tactic:
rw [eq_empty_of_isEmpty s, prod_empty]
/-- The product of `f` over `insert a s` is the same as
the product over `s`, as long as `a` is in `s` or `f a = 1`. -/
@[to_additive (attr := simp) "The sum of `f` over `insert a s` is the same as
the sum over `s`, as long as `a` is in `s` or `f a = 0`."]
theorem prod_insert_of_eq_one_if_not_mem [DecidableEq α] (h : a ∉ s → f a = 1) :
    ∏ x in insert a s, f x = ∏ x in s, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
h : a ∉ s → f a = 1
⊢ ∏ x in insert a s, f x = ∏ x in s, f x

Next tactic:
by_cases hm : a ∈ s
/-- The product of `f` over `insert a s` is the same as
the product over `s`, as long as `a` is in `s` or `f a = 1`. -/
@[to_additive (attr := simp) "The sum of `f` over `insert a s` is the same as
the sum over `s`, as long as `a` is in `s` or `f a = 0`."]
theorem prod_insert_of_eq_one_if_not_mem [DecidableEq α] (h : a ∉ s → f a = 1) :
    ∏ x in insert a s, f x = ∏ x in s, f x := by
  by_cases hm : a ∈ s
  · 

Proof state:
case pos
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
h : a ∉ s → f a = 1
hm : a ∈ s
⊢ ∏ x in insert a s, f x = ∏ x in s, f x

Next tactic:
simp_rw [insert_eq_of_mem hm]
/-- The product of `f` over `insert a s` is the same as
the product over `s`, as long as `a` is in `s` or `f a = 1`. -/
@[to_additive (attr := simp) "The sum of `f` over `insert a s` is the same as
the sum over `s`, as long as `a` is in `s` or `f a = 0`."]
theorem prod_insert_of_eq_one_if_not_mem [DecidableEq α] (h : a ∉ s → f a = 1) :
    ∏ x in insert a s, f x = ∏ x in s, f x := by
  by_cases hm : a ∈ s
  · simp_rw [insert_eq_of_mem hm]
  · 

Proof state:
case neg
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
h : a ∉ s → f a = 1
hm : a ∉ s
⊢ ∏ x in insert a s, f x = ∏ x in s, f x

Next tactic:
rw [prod_insert hm, h hm, one_mul]
@[to_additive]
theorem prod_insert_div {M : Type*} [CommGroup M] [DecidableEq α] (ha : a ∉ s) {f : α → M} :
    (∏ x in insert a s, f x) / f a = ∏ x in s, f x := by 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝² : CommMonoid β
M : Type u_2
inst✝¹ : CommGroup M
inst✝ : DecidableEq α
ha : a ∉ s
f : α → M
⊢ (∏ x in insert a s, f x) / f a = ∏ x in s, f x

Next tactic:
simp [ha]
@[to_additive]
theorem prod_pair [DecidableEq α] {a b : α} (h : a ≠ b) :
    (∏ x in ({a, b} : Finset α), f x) = f a * f b := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a✝ : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
a b : α
h : a ≠ b
⊢ ∏ x in {a, b}, f x = f a * f b

Next tactic:
rw [prod_insert (not_mem_singleton.2 h), prod_singleton]
@[to_additive (attr := simp)]
theorem prod_const_one : (∏ _x in s, (1 : β)) = 1 := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
⊢ ∏ _x in s, 1 = 1

Next tactic:
simp only [Finset.prod, Multiset.map_const', Multiset.prod_replicate, one_pow]
@[to_additive (attr := simp)]
theorem prod_map (s : Finset α) (e : α ↪ γ) (f : γ → β) :
    ∏ x in s.map e, f x = ∏ x in s, f (e x) := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
e : α ↪ γ
f : γ → β
⊢ ∏ x in map e s, f x = ∏ x in s, f (e x)

Next tactic:
rw [Finset.prod, Finset.map_val, Multiset.map_map]
@[to_additive (attr := simp)]
theorem prod_map (s : Finset α) (e : α ↪ γ) (f : γ → β) :
    ∏ x in s.map e, f x = ∏ x in s, f (e x) := by
  rw [Finset.prod, Finset.map_val, Multiset.map_map]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
e : α ↪ γ
f : γ → β
⊢ Multiset.prod (Multiset.map ((fun x => f x) ∘ ⇑e) s.val) = ∏ x in s, f (e x)

Next tactic:
rfl
@[to_additive (attr := congr)]
theorem prod_congr (h : s₁ = s₂) : (∀ x ∈ s₂, f x = g x) → s₁.prod f = s₂.prod g := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
h : s₁ = s₂
⊢ (∀ x ∈ s₂, f x = g x) → Finset.prod s₁ f = Finset.prod s₂ g

Next tactic:
rw [h]
@[to_additive (attr := congr)]
theorem prod_congr (h : s₁ = s₂) : (∀ x ∈ s₂, f x = g x) → s₁.prod f = s₂.prod g := by
  rw [h]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
h : s₁ = s₂
⊢ (∀ x ∈ s₂, f x = g x) → Finset.prod s₂ f = Finset.prod s₂ g

Next tactic:
exact fold_congr
@[to_additive]
theorem prod_disjUnion (h) :
    ∏ x in s₁.disjUnion s₂ h, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
h : Disjoint s₁ s₂
⊢ ∏ x in disjUnion s₁ s₂ h, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x

Next tactic:
refine' Eq.trans _ (fold_disjUnion h)
@[to_additive]
theorem prod_disjUnion (h) :
    ∏ x in s₁.disjUnion s₂ h, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x := by
  refine' Eq.trans _ (fold_disjUnion h)
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
h : Disjoint s₁ s₂
⊢ ∏ x in disjUnion s₁ s₂ h, f x = fold (fun x x_1 => x * x_1) (1 * 1) (fun x => f x) (disjUnion s₁ s₂ h)

Next tactic:
rw [one_mul]
@[to_additive]
theorem prod_disjUnion (h) :
    ∏ x in s₁.disjUnion s₂ h, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x := by
  refine' Eq.trans _ (fold_disjUnion h)
  rw [one_mul]
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
h : Disjoint s₁ s₂
⊢ ∏ x in disjUnion s₁ s₂ h, f x = fold (fun x x_1 => x * x_1) 1 (fun x => f x) (disjUnion s₁ s₂ h)

Next tactic:
rfl
@[to_additive]
theorem prod_disjiUnion (s : Finset ι) (t : ι → Finset α) (h) :
    ∏ x in s.disjiUnion t h, f x = ∏ i in s, ∏ x in t i, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
s : Finset ι
t : ι → Finset α
h : Set.PairwiseDisjoint (↑s) t
⊢ ∏ x in disjiUnion s t h, f x = ∏ i in s, ∏ x in t i, f x

Next tactic:
refine' Eq.trans _ (fold_disjiUnion h)
@[to_additive]
theorem prod_disjiUnion (s : Finset ι) (t : ι → Finset α) (h) :
    ∏ x in s.disjiUnion t h, f x = ∏ i in s, ∏ x in t i, f x := by
  refine' Eq.trans _ (fold_disjiUnion h)
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
s : Finset ι
t : ι → Finset α
h : Set.PairwiseDisjoint (↑s) t
⊢ ∏ x in disjiUnion s t h, f x =
    fold (fun x x_1 => x * x_1) (fold (fun x x_1 => x * x_1) 1 (fun i => 1) s) (fun x => f x) (disjiUnion s t h)

Next tactic:
dsimp [Finset.prod, Multiset.prod, Multiset.fold, Finset.disjUnion, Finset.fold]
@[to_additive]
theorem prod_disjiUnion (s : Finset ι) (t : ι → Finset α) (h) :
    ∏ x in s.disjiUnion t h, f x = ∏ i in s, ∏ x in t i, f x := by
  refine' Eq.trans _ (fold_disjiUnion h)
  dsimp [Finset.prod, Multiset.prod, Multiset.fold, Finset.disjUnion, Finset.fold]
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
s : Finset ι
t : ι → Finset α
h : Set.PairwiseDisjoint (↑s) t
⊢ Multiset.foldr (fun x x_1 => x * x_1) (_ : ∀ (x y z : β), x * (y * z) = y * (x * z)) 1
      (Multiset.map (fun x => f x) (Multiset.bind s.val fun a => (t a).val)) =
    Multiset.foldr (fun x x_1 => x * x_1) (_ : LeftCommutative fun x x_1 => x * x_1)
      (Multiset.foldr (fun x x_1 => x * x_1) (_ : LeftCommutative fun x x_1 => x * x_1) 1
        (Multiset.map (fun i => 1) s.val))
      (Multiset.map (fun x => f x) (Multiset.bind s.val fun a => (t a).val))

Next tactic:
congr
@[to_additive]
theorem prod_disjiUnion (s : Finset ι) (t : ι → Finset α) (h) :
    ∏ x in s.disjiUnion t h, f x = ∏ i in s, ∏ x in t i, f x := by
  refine' Eq.trans _ (fold_disjiUnion h)
  dsimp [Finset.prod, Multiset.prod, Multiset.fold, Finset.disjUnion, Finset.fold]
  congr
  

Proof state:
case e_b
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f g : α → β
inst✝ : CommMonoid β
s : Finset ι
t : ι → Finset α
h : Set.PairwiseDisjoint (↑s) t
⊢ 1 =
    Multiset.foldr (fun x x_1 => x * x_1) (_ : LeftCommutative fun x x_1 => x * x_1) 1 (Multiset.map (fun i => 1) s.val)

Next tactic:
exact prod_const_one.symm
@[to_additive]
theorem prod_union [DecidableEq α] (h : Disjoint s₁ s₂) :
    ∏ x in s₁ ∪ s₂, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
h : Disjoint s₁ s₂
⊢ ∏ x in s₁ ∪ s₂, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x

Next tactic:
rw [← prod_union_inter, disjoint_iff_inter_eq_empty.mp h]
@[to_additive]
theorem prod_union [DecidableEq α] (h : Disjoint s₁ s₂) :
    ∏ x in s₁ ∪ s₂, f x = (∏ x in s₁, f x) * ∏ x in s₂, f x := by
  rw [← prod_union_inter, disjoint_iff_inter_eq_empty.mp h]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
h : Disjoint s₁ s₂
⊢ ∏ x in s₁ ∪ s₂, f x = (∏ x in s₁ ∪ s₂, f x) * ∏ x in ∅, f x

Next tactic:
exact (mul_one _).symm
@[to_additive]
theorem prod_filter_mul_prod_filter_not
    (s : Finset α) (p : α → Prop) [DecidablePred p] [∀ x, Decidable (¬p x)] (f : α → β) :
    (∏ x in s.filter p, f x) * ∏ x in s.filter fun x => ¬p x, f x = ∏ x in s, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝² : CommMonoid β
s : Finset α
p : α → Prop
inst✝¹ : DecidablePred p
inst✝ : (x : α) → Decidable ¬p x
f : α → β
⊢ (∏ x in filter p s, f x) * ∏ x in filter (fun x => ¬p x) s, f x = ∏ x in s, f x

Next tactic:
have := Classical.decEq α
@[to_additive]
theorem prod_filter_mul_prod_filter_not
    (s : Finset α) (p : α → Prop) [DecidablePred p] [∀ x, Decidable (¬p x)] (f : α → β) :
    (∏ x in s.filter p, f x) * ∏ x in s.filter fun x => ¬p x, f x = ∏ x in s, f x := by
  have := Classical.decEq α
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝² : CommMonoid β
s : Finset α
p : α → Prop
inst✝¹ : DecidablePred p
inst✝ : (x : α) → Decidable ¬p x
f : α → β
this : DecidableEq α
⊢ (∏ x in filter p s, f x) * ∏ x in filter (fun x => ¬p x) s, f x = ∏ x in s, f x

Next tactic:
rw [← prod_union (disjoint_filter_filter_neg s s p), filter_union_filter_neg_eq]
@[to_additive (attr := simp)]
theorem prod_to_list (s : Finset α) (f : α → β) : (s.toList.map f).prod = s.prod f := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
s : Finset α
f : α → β
⊢ List.prod (List.map f (toList s)) = Finset.prod s f

Next tactic:
rw [Finset.prod, ← Multiset.coe_prod, ← Multiset.coe_map, Finset.coe_toList]
@[to_additive]
theorem _root_.Equiv.Perm.prod_comp (σ : Equiv.Perm α) (s : Finset α) (f : α → β)
    (hs : { a | σ a ≠ a } ⊆ s) : (∏ x in s, f (σ x)) = ∏ x in s, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
σ : Equiv.Perm α
s : Finset α
f : α → β
hs : {a | σ a ≠ a} ⊆ ↑s
⊢ ∏ x in s, f (σ x) = ∏ x in s, f x

Next tactic:
convert (prod_map s σ.toEmbedding f).symm
@[to_additive]
theorem _root_.Equiv.Perm.prod_comp (σ : Equiv.Perm α) (s : Finset α) (f : α → β)
    (hs : { a | σ a ≠ a } ⊆ s) : (∏ x in s, f (σ x)) = ∏ x in s, f x := by
  convert (prod_map s σ.toEmbedding f).symm
  

Proof state:
case h.e'_3.h
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
σ : Equiv.Perm α
s : Finset α
f : α → β
hs : {a | σ a ≠ a} ⊆ ↑s
⊢ s = map (Equiv.toEmbedding σ) s

Next tactic:
exact (map_perm hs).symm
@[to_additive]
theorem _root_.Equiv.Perm.prod_comp' (σ : Equiv.Perm α) (s : Finset α) (f : α → α → β)
    (hs : { a | σ a ≠ a } ⊆ s) : (∏ x in s, f (σ x) x) = ∏ x in s, f x (σ.symm x) := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
σ : Equiv.Perm α
s : Finset α
f : α → α → β
hs : {a | σ a ≠ a} ⊆ ↑s
⊢ ∏ x in s, f (σ x) x = ∏ x in s, f x (σ.symm x)

Next tactic:
convert σ.prod_comp s (fun x => f x (σ.symm x)) hs
@[to_additive]
theorem _root_.Equiv.Perm.prod_comp' (σ : Equiv.Perm α) (s : Finset α) (f : α → α → β)
    (hs : { a | σ a ≠ a } ⊆ s) : (∏ x in s, f (σ x) x) = ∏ x in s, f x (σ.symm x) := by
  convert σ.prod_comp s (fun x => f x (σ.symm x)) hs
  

Proof state:
case h.e'_2.a.h.e'_2
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝ : CommMonoid β
σ : Equiv.Perm α
s : Finset α
f : α → α → β
hs : {a | σ a ≠ a} ⊆ ↑s
x✝ : α
a✝ : x✝ ∈ s
⊢ x✝ = σ.symm (σ x✝)

Next tactic:
rw [Equiv.symm_apply_apply]
@[to_additive]
theorem IsCompl.prod_mul_prod {s t : Finset α} (h : IsCompl s t) (f : α → β) :
    (∏ i in s, f i) * ∏ i in t, f i = ∏ i, f i :=
  (Finset.prod_disjUnion h.disjoint).symm.trans <| by
    

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : Fintype α
inst✝ : CommMonoid β
s t : Finset α
h : IsCompl s t
f : α → β
⊢ ∏ x in disjUnion s t (_ : Disjoint s t), f x = ∏ i : α, f i

Next tactic:
classical rw [Finset.disjUnion_eq_union, ← Finset.sup_eq_union, h.sup_eq_top]; rfl
@[to_additive]
theorem IsCompl.prod_mul_prod {s t : Finset α} (h : IsCompl s t) (f : α → β) :
    (∏ i in s, f i) * ∏ i in t, f i = ∏ i, f i :=
  (Finset.prod_disjUnion h.disjoint).symm.trans <| by
    classical 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : Fintype α
inst✝ : CommMonoid β
s t : Finset α
h : IsCompl s t
f : α → β
⊢ ∏ x in disjUnion s t (_ : Disjoint s t), f x = ∏ i : α, f i

Next tactic:
rw [Finset.disjUnion_eq_union, ← Finset.sup_eq_union, h.sup_eq_top]
@[to_additive]
theorem IsCompl.prod_mul_prod {s t : Finset α} (h : IsCompl s t) (f : α → β) :
    (∏ i in s, f i) * ∏ i in t, f i = ∏ i, f i :=
  (Finset.prod_disjUnion h.disjoint).symm.trans <| by
    classical rw [Finset.disjUnion_eq_union, ← Finset.sup_eq_union, h.sup_eq_top]; 

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s✝ s₁ s₂ : Finset α
a : α
f✝ g : α → β
inst✝¹ : Fintype α
inst✝ : CommMonoid β
s t : Finset α
h : IsCompl s t
f : α → β
⊢ ∏ x in ⊤, f x = ∏ i : α, f i

Next tactic:
rfl
@[to_additive]
theorem prod_sdiff [DecidableEq α] (h : s₁ ⊆ s₂) :
    (∏ x in s₂ \ s₁, f x) * ∏ x in s₁, f x = ∏ x in s₂, f x := by
  

Proof state:
ι : Type u_1
β : Type u
α : Type v
γ : Type w
s s₁ s₂ : Finset α
a : α
f g : α → β
inst✝¹ : CommMonoid β
inst✝ : DecidableEq α
h : s₁ ⊆ s₂
⊢ (∏ x in s₂ \ s₁, f x) * ∏ x in s₁, f x = ∏ x in s₂, f x

Next tactic:
rw [← prod_union sdiff_disjoint, sdiff_union_of_subset h]